OA权限模块根据用户权限显示不同的操作按钮
来源:互联网 发布:淘宝购物车营销 规则 编辑:程序博客网 时间:2024/05/21 14:47
前几篇博文介绍了如何根据不同的用户权限,实现不同的界面菜单,在权限模块中,属于比较粗粒度的划分。我们如果想控制一个用户的权限到具体的按钮应该怎么是实现呢?这篇博文就为大家简单的介绍一下。
一、情景导入
下图是我系统中的一个模块,具有添加删除修改的三个权限操作,如图:
现在我来了一共用户,我不想让他具有添加和修改权限怎么做呢?
二、具体实现
1.首先,我们一起来看看编写好的jsp界面
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%><html><head> <title>岗位列表</title> <%@ include file="/WEB-INF/jsp/public/commons.jspf" %></head><body> <div id="Title_bar"> <div id="Title_bar_Head"> <div id="Title_Head"></div> <div id="Title"><!--页面标题--> <img border="0" width="13" height="13" src="${pageContext.request.contextPath}/style/images/title_arrow.gif"/> 岗位管理 </div> <div id="Title_End"></div> </div></div><div id="MainArea"> <table cellspacing="0" cellpadding="0" class="TableStyle"> <!-- 表头--> <thead> <tr align="CENTER" valign="MIDDLE" id="TableTitle"> <td width="200px">岗位名称</td> <td width="300px">岗位说明</td> <td>相关操作</td> </tr> </thead><!--显示数据列表--> <tbody id="TableData" class="dataContainer" datakey="roleList"> <s:iterator value="#roleList"><tr class="TableDetail1 template"><td>${name} </td><td>${description} </td><td><s:a action="role_delete?id=%{id}" onclick="return confirm('确定要删除吗?')">删除</s:a><s:a action="role_editUI?id=%{id}">修改</s:a><s:a action="role_setPrivilegeUI?id=%{id}">设置权限</s:a></td></tr> </s:iterator> </tbody> </table> <!-- 其他功能超链接 --> <div id="TableTail"><div id="TableTail_inside"><s:a action="role_addUI"><img src="${pageContext.request.contextPath}/style/images/createNew.png" /></s:a> </div> </div></div></body></html>
我们新建一个和底层中一模一样的a标签对应的类,这样编译器如果能在我们的classpath路径下找到我们需要的类,就不会再去struts的core包中去寻找了。创建好相应的包和类后,我们对它的doEndTag方法进行改写:
package org.apache.struts2.views.jsp.ui;import org.apache.struts2.components.Anchor;import org.apache.struts2.components.Component;import cn.itcast.oa.domain.User;import com.opensymphony.xwork2.util.ValueStack;/** * @see Anchor */public class AnchorTag extends AbstractClosingTag {private static final long serialVersionUID = -1034616578492431113L;protected String href;protected String includeParams;protected String scheme;protected String action;protected String namespace;protected String method;protected String encode;protected String includeContext;protected String escapeAmp;protected String portletMode;protected String windowState;protected String portletUrlType;protected String anchor;protected String forceAddSchemeHostAndPort;//改写doEndTag方法@Overridepublic int doEndTag() throws JspException {// 当前登录用户User user = (User) pageContext.getSession().getAttribute("user");// 当前准备显示的链接对应的权限URL// 在开头加上'/'String privUrl = "/" + action;if (user.hasPrivilegeByUrl(privUrl)) {// 正常的生成并显示超链接 标签,并继续执行页面中后面的代码return super.doEndTag(); } else {// 不生成与显示超链接 标签,只是继续执行页面中后面的代码return EVAL_PAGE; }}public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) {return new Anchor(stack, req, res);}protected void populateParams() {super.populateParams();Anchor tag = (Anchor) component;tag.setHref(href);tag.setIncludeParams(includeParams);tag.setScheme(scheme);tag.setValue(value);tag.setMethod(method);tag.setNamespace(namespace);tag.setAction(action);tag.setPortletMode(portletMode);tag.setPortletUrlType(portletUrlType);tag.setWindowState(windowState);tag.setAnchor(anchor);if (encode != null) {tag.setEncode(Boolean.valueOf(encode).booleanValue());}if (includeContext != null) {tag.setIncludeContext(Boolean.valueOf(includeContext).booleanValue());}if (escapeAmp != null) {tag.setEscapeAmp(Boolean.valueOf(escapeAmp).booleanValue());}if (forceAddSchemeHostAndPort != null) {tag.setForceAddSchemeHostAndPort(Boolean.valueOf(forceAddSchemeHostAndPort).booleanValue());}}public void setHref(String href) {this.href = href;}public void setEncode(String encode) {this.encode = encode;}public void setIncludeContext(String includeContext) {this.includeContext = includeContext;}public void setEscapeAmp(String escapeAmp) {this.escapeAmp = escapeAmp;}public void setIncludeParams(String name) {includeParams = name;}public void setAction(String action) {this.action = action;}public void setNamespace(String namespace) {this.namespace = namespace;}public void setMethod(String method) {this.method = method;}public void setScheme(String scheme) {this.scheme = scheme;}public void setValue(String value) {this.value = value;}public void setPortletMode(String portletMode) {this.portletMode = portletMode;}public void setPortletUrlType(String portletUrlType) {this.portletUrlType = portletUrlType;}public void setWindowState(String windowState) {this.windowState = windowState;}public void setAnchor(String anchor) {this.anchor = anchor;}public void setForceAddSchemeHostAndPort(String forceAddSchemeHostAndPort) {this.forceAddSchemeHostAndPort = forceAddSchemeHostAndPort;}}
3.在User实体中,添加根据url方法判断有无权限的方法
在上一篇博文中我们已经提到了用户登录用根据用户的权限信息来判断用户可以访问的菜单列表,并把它们放到了application域中,我们判断的时候从application域中将该用户所具有的权限菜单的url拿到,然后循环便利,对比我们的用户是否具有该项权限,如果具有则正常执行Tag标签,如果不具有则隐藏标签。代码如下:
package cn.itcast.oa.domain;import java.util.Collection;import java.util.HashSet;import java.util.Set;import com.opensymphony.xwork2.ActionContext;/** * 用户 * * @author tyg * */public class User implements java.io.Serializable{private Long id;private Department department;private Set<Role> roles = new HashSet<Role>();private String loginName; // 登录名private String password; // 密码private String name; // 真实姓名private String gender; // 性别private String phoneNumber; // 电话号码private String email; // 电子邮件private String description; // 说明/** * 判断本用户是否有指定名称的权限 * * @param name * @return */public boolean hasPrivilegeByName(String name) {// 超级管理有所有的权限if (isAdmin()) {return true;}// 普通用户要判断是否含有这个权限for (Role role : roles) {for (Privilege priv : role.getPrivileges()) {if (priv.getName().equals(name)) {return true;}}}return false;}/** * 判断本用户是否有指定URL的权限 * * @param privUrl * @return */public boolean hasPrivilegeByUrl(String privUrl) {// 超级管理有所有的权限if (isAdmin()) {return true;}// 去掉?后面的参数int pos = privUrl.indexOf("?");if (pos > -1) {//如果存在?则截取后面的参数privUrl = privUrl.substring(0, pos);}// 去掉url中的UI后缀if (privUrl.endsWith("UI")) {//如果以UI结尾则截取UI之前的urlprivUrl = privUrl.substring(0, privUrl.length() - 2);}// 如果本URL不需要控制,则登录用户就可以使用Collection<String> allPrivilegeUrls = (Collection<String>) ActionContext.getContext().getApplication().get("allPrivilegeUrls");if (!allPrivilegeUrls.contains(privUrl)) {return true;} else {// 普通用户要判断是否含有这个权限for (Role role : roles) {for (Privilege priv : role.getPrivileges()) {if (privUrl.equals(priv.getUrl())) {return true;}}}return false;}}/** * 判断本用户是否是超级管理员 * * @return */public boolean isAdmin() {return "admin".equals(loginName);}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public Department getDepartment() {return department;}public void setDepartment(Department department) {this.department = department;}public Set<Role> getRoles() {return roles;}public void setRoles(Set<Role> roles) {this.roles = roles;}public String getLoginName() {return loginName;}public void setLoginName(String loginName) {this.loginName = loginName;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public String getPhoneNumber() {return phoneNumber;}public void setPhoneNumber(String phoneNumber) {this.phoneNumber = phoneNumber;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}}
三、拦截每个请求的权限
上面两个步骤的操作,只是显示了如果用户登录,显示与其权限相对应的操作按钮,只是实现了界面上的控制效果,实际上,如果真正在浏览器输入相应的url的话,还是能够访问对应的权限的,那么我们应该怎样处理这一种情况呢?拦截器无疑是一个好的办法。如果用户尚未登录,则跳转到登录界面,否则根据url判断用户的权限,有权限则访问,没有则跳转到错误页。
1.编写拦截器
package cn.itcast.oa.util;import cn.itcast.oa.domain.User;import com.opensymphony.xwork2.ActionContext;import com.opensymphony.xwork2.ActionInvocation;import com.opensymphony.xwork2.interceptor.AbstractInterceptor;public class CheckPrivilegeInterceptor extends AbstractInterceptor {//对所有请求的url进行拦截public String intercept(ActionInvocation invocation) throws Exception {// 获取信息User user = (User) ActionContext.getContext().getSession().get("user"); // 当前登录用户String namespace = invocation.getProxy().getNamespace();String actionName = invocation.getProxy().getActionName();String privUrl = namespace + actionName; // 对应的权限URL// 如果未登录if (user == null) {if (privUrl.startsWith("/user_login")) { // "/user_loginUI", "/user_login"// 如果是去登录,就放行return invocation.invoke();} else {// 如果不是去登录,就转到登录页面return "loginUI";}}// 如果已登 录,就判断权限else {if (user.hasPrivilegeByUrl(privUrl)) {// 如果有权限,就放行return invocation.invoke();} else {// 如果没有权限,就转到提示页面return "noPrivilegeError";}}}}
2.在struts.xml文件中配置
<interceptors> <!-- 声明拦截器 --> <interceptor name="checkPrivilege" class="cn.itcast.oa.util.CheckPrivilegeInterceptor"></interceptor> <!-- 重新定义默认的拦截器栈 --> <interceptor-stack name="defaultStack"> <interceptor-ref name="checkPrivilege"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </interceptor-stack> </interceptors><!-- 全局的Result配置 --><global-results><result name="loginUI">/WEB-INF/jsp/userAction/loginUI.jsp</result><result name="noPrivilegeError">/noPrivilegeError.jsp</result></global-results>
总结:
这一部分是权限模块中关于权限控制非常经典的实现,主要的知识有:
1.重新struts2的Tag标签的doEndTag方法;
2.在User实体中添加对根据url开控制用户权限的方法;
3.根据url判断权限的方法中对字符串的操作,以前学习的又重新回顾了一遍`(*∩_∩*)′
4.使用拦截器对所有action的拦截并执行相应的操作
- OA权限模块根据用户权限显示不同的操作按钮
- OA权限模块根据用户权限显示不同的操作按钮
- OA权限模块根据用户权限显示不同的菜单
- OA权限模块根据用户权限显示不同的菜单
- OA权限模块根据用户权限显示不同的菜单
- Dynamics CRM 根据用户权限不同来进行按钮的显示和隐藏的功能
- 使用shiro框架的标签来根据权限显示按钮
- Django 权限认证 编写 -- 根据不同的用户,设置不同的显示和访问权限
- Yii: 如何在CGridView组件中根据不同的记录行数据显示不同的操作
- 按钮的背景图片根据状态的不同而显示不同的图片,网上有介绍相关的方法。
- sharepoint 2010 如何根据权限控制Ribbon区域功能按钮的显示
- [Phonegap+Sencha Touch] 移动开发47 NavigationView如何根据不同的View显示不同的顶栏按钮
- iOS 在一个屏幕中根据不同的按钮创建不同的 view 默认显示第一个
- 点击一个按钮后,它会根据不同的情况执行不同的操作,执行客户段的应用程序
- ASP根据用户权限判断显示的列标题
- Android根据不同身份配置APP对应的不同模块
- 根据时间显示不同的广告
- 根据roles显示不同的sitemap
- 关于字符编码
- URL
- nagios监控mysql
- VS中lib和dll的使用
- Unity3d优化之从Draw Calls到GC
- OA权限模块根据用户权限显示不同的操作按钮
- ADB工具介绍(Android Debug Bridge),摘选重点翻译,请随便喷
- 求一个数的二进制数中1的个数
- log4j.properties配置详解
- Xamarin 设置ListView组头的高度
- android从服务器端解析json数据
- jsp,servlet,javascript,xml,html之间的关系
- PHP异步执行技巧
- POJ 3320 Jessica's Reading Problem (原来标题在这里改……)