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>


          2.重写struts2中的<s:a>Tag标签


    我们新建一个和底层中一模一样的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的拦截并执行相应的操作

    

   

0 0