基于Struts2框架的权限管理系统+自定义标签精确到页面按钮级权限

最近把项目的后台权限管理系统优化了一下子,项目原来的权限管理只能精确到页面级的权限,通过添加自定义标签来做页面按钮级别的权限

在这里主要分享下如果自定义Struts2标签来做权限限制。

借鉴资料:http://my.oschina.net/winHerson/blog/117313

思路:

1、通过在页面引入自定义标签,在标签中传入需要判断的权限

2、在自定义标签实现内部做权限判定,引用效果

<!-- 自定义按钮,判断是否具有该按钮权限,如果有则显示,没有就不显示 -->
<btn:b type="button" uri="/user/updateInfo.action" clazz="updateInfo" value="修改"></btn:b>


其中的 type,uri,clazz,value都是可以自己定制的,可以灵活的根据项目需求来编写对应的标签。

下面就来详细介绍下我自己实现自定义按钮标签的实现过程:

主要需要类有两个:TagButton.java 继承 sturts2的 ComponentTagSupport,用来获取如上图代码中jsp页面传递过来的属性值。

RightButton 继承 struts2 的 Component,用来获取struts2值栈中的值。

 

TagButton.java源码如下:

package com.zqb.tag;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.struts2.components.Component;
import org.apache.struts2.views.jsp.ComponentTagSupport;

import com.opensymphony.xwork2.util.ValueStack;
import com.zqb.pojo.TbAdminUser;

/**
 * 自定义权限按钮
 * 作用:检测当前用户的是否具有按钮点击权限,如果有,则在页面上展示该按钮
 * 如果没有,则不展示按钮
 * @author WeiRuFeng
 *
 */
public class TagButton extends ComponentTagSupport{
    
    /**
     * 
     */
    private static final long serialVersionUID = 2696607950829049879L;

    /**
     * 页面标签属性,权限操作路径
     */
    private String uri;
    
    /**
     * 按钮名称
     */
    private String name;
    
    /**
     * 按钮type属性
     */
    private String type;
    
    /**
     * 按钮class属性
     */
    private String clazz;
    
    /**
     * 按钮ID属性
     */
    private String id;
    
    /**
     * 按钮value属性
     */
    private String value;
    
    HttpServletRequest req;
    
    HttpServletResponse resp;

    /**
     * 构造方法,从值栈里面获取数据
     */
    @Override
    public Component getBean(ValueStack stack, HttpServletRequest req,
            HttpServletResponse resp) {
        this.req = req;
        this.resp = resp;
        return new RightButton(stack, req);
    }
    

    @Override
    protected void populateParams() {
        super.populateParams();
        RightButton button = (RightButton)component;
        button.setName(name);
        button.setValue(value);
        button.setId(id);
        button.setType(type);
        button.setClazz(clazz);
        button.setUri(uri);
        HttpSession session = req.getSession();
        TbAdminUser adminUser = (TbAdminUser) session.getAttribute("adminUser");
        button.setAdminUser(adminUser);
    }


    public String getUri() {
        return uri;
    }


    public void setUri(String uri) {
        this.uri = uri;
    }


    public String getName() {
        return name;
    }


    public void setName(String name) {
        this.name = name;
    }


    public String getType() {
        return type;
    }


    public void setType(String type) {
        this.type = type;
    }


    public String getClazz() {
        return clazz;
    }


    public void setClazz(String clazz) {
        this.clazz = clazz;
    }


    @Override
    public String getId() {
        return id;
    }


    @Override
    public void setId(String id) {
        this.id = id;
    }


    public String getValue() {
        return value;
    }


    public void setValue(String value) {
        this.value = value;
    }


    public HttpServletRequest getReq() {
        return req;
    }


    public void setReq(HttpServletRequest req) {
        this.req = req;
    }


    public HttpServletResponse getResp() {
        return resp;
    }


    public void setResp(HttpServletResponse resp) {
        this.resp = resp;
    }
}

其中重写了两个方法:getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse resp) ,此方法就是获得一个基本类的对象。在基本类里面需要有传入ValueStack的构造函数,如果基本类逻辑里面需要request或者response,那 么需要有传入ValueStack stack, HttpServletRequest req, HttpServletResponse res的构造函数;

 

RightButton.java 继承Component类是为了从Struts2中的ValueStack中获得相对应的值,其中有个用户对象属性,作用是用来记录当前用户的信息,该对象是在当前的用户登录的是存入session中的,我们在上面那个类中从session中取出来了,然后在当前这个类里面根据用户的角色id去查找权限表,最终判断是否具有操作权限

package com.zqb.tag;

import java.io.IOException;
import java.io.Writer;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.components.Component;

import com.opensymphony.xwork2.util.ValueStack;
import com.zqb.pojo.TbAdminUser;
import com.zqb.service.IPermissionService;
import com.zqb.service.impl.PermissionServiceImpl;
import com.zqb.wrf.util.Tools;

/**
 * 自定义权限按钮
 * 如果该按钮具有权限,则显示该权限按钮
 * 否则不显示
 * @author WeiRuFeng
 * @version 1.0.0
 */
public class RightButton extends Component{
    
    /**
     * 操作权限路径
     */
    private String uri;

    /**
     * 按钮名称
     */
    private String name;
    
    /**
     * 按钮type属性
     */
    private String type;
    
    /**
     * 按钮class属性
     */
    private String clazz;
    
    /**
     * 按钮ID属性
     */
    private String id;
    
    /**
     * 按钮value属性
     */
    private String value;
    
    /**
     * 登录用户对象
     */
    private TbAdminUser adminUser;
    
    boolean flag = false;
    
    IPermissionService permissionService = new PermissionServiceImpl();
    
    HttpServletRequest req ;
    public RightButton(ValueStack stack,HttpServletRequest req) {
        super(stack);
        this.req = req;
    }
    
    @Override
    public boolean start(Writer writer) {
        /**
         * 是否能够访问该权限操作路径,业务逻辑在这里做判断
         */
        flag = permissionService.findPermission(uri,adminUser);
        //测试
//        flag = true;
        if(flag){
            StringBuffer button = new StringBuffer();
            //"<input type="button" class="updateInfo" value="修改"/>"
            button.append("<input ");
            
            //判断各属性是否为空,为空则不添加相应的属性
            if(!Tools.isEmpty(type)){
                button.append(" type=\""+type+"\"");
            }
            if(!Tools.isEmpty(id)){
                button.append(" id=\""+id+"\"");
            }
            if(!Tools.isEmpty(value)){
                button.append(" value=\""+value+"\"");
            }
            if(!Tools.isEmpty(clazz)){
                button.append(" class=\""+clazz+"\"");
            }
            if(!Tools.isEmpty(name)){
                button.append(" name=\""+name+"\"");
            }
            System.out.println("---------->button:"+button);
            try {
                writer.write(button.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else{
            System.out.println("-----start--------没有该权限");
        }
        return super.start(writer);
    }
    
    @Override
    protected boolean end(Writer writer, String body, boolean flag) {
        // TODO Auto-generated method stub业务逻辑在这里做判断
        flag = permissionService.findPermission(uri,adminUser);
        //测试
//        flag = true;
        if(flag){
            try {
                writer.write(" />");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else{
            System.out.println("-----end-----没有改权限");
        }
        return super.end(writer, body, true);
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getClazz() {
        return clazz;
    }
    public void setClazz(String clazz) {
        this.clazz = clazz;
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
    public TbAdminUser getAdminUser() {
        return adminUser;
    }
    public void setAdminUser(TbAdminUser adminUser) {
        this.adminUser = adminUser;
    }
    public String getUri() {
        return uri;
    }
    public void setUri(String uri) {
        this.uri = uri;
    }
    public HttpServletRequest getReq() {
        return req;
    }
    public void setReq(HttpServletRequest req) {
        this.req = req;
    }
    
}
其中 return super.end(writer, body, true);第三个参数我传递的是true,因为没有去查源码,暂时没有去测试false是表示什么意思。

创建tld库文件,文件是放在WEB-INF文件夹下面,和xml文件同级:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
    <tlib-version>2.2.3</tlib-version>
    <jsp-version>1.2</jsp-version>
  <!--页面调用标签的快捷方式如:<btn:b> .. -->
<short-name>btn</short-name>
  <!--页面引入标签的uri-->
<uri>/struts-btn-tags</uri> <display-name>"Struts Tags"</display-name> <description> <![CDATA["自定义按钮标签,用来判断当前用户的该按钮是否具有权限"]]> </description> <tag>
     <!--标签名:<btn:b></btn:b> -->
<name>b</name>
     <!--标签对象-->
<tag-class>com.zqb.tag.TagButton</tag-class>
     <!--标签使用作用范围-->
<body-content>JSP</body-content>
     <!--标签属性-->
<attribute> <name>uri</name>
       <!--是否是必须的-->
<required>true</required> <rtexprvalue>false</rtexprvalue> <description><![CDATA["需要判断的操作权限路径"]]></description> </attribute> <attribute> <name>name</name> <required>false</required> <rtexprvalue>false</rtexprvalue> <description><![CDATA["按钮的name属性值"]]></description> </attribute> <attribute> <name>type</name> <required>true</required> <rtexprvalue>false</rtexprvalue> <description><![CDATA["按钮的type属性值"]]></description> </attribute> <attribute> <name>clazz</name> <required>false</required> <rtexprvalue>false</rtexprvalue> <description><![CDATA["按钮的class属性值"]]></description> </attribute> <attribute> <name>id</name> <required>false</required> <rtexprvalue>false</rtexprvalue> <description><![CDATA["按钮的id属性值"]]></description> </attribute> <attribute> <name>value</name> <required>false</required> <rtexprvalue>false</rtexprvalue> <description><![CDATA["按钮的value属性值"]]></description> </attribute> </tag> </taglib>

这里主要说下需要注意的地方:其中的attribute节点的个数是和类里面定义标签属性相对应的

 

在xml中添加标签库说明

<jsp-config>
        <taglib>
            <taglib-uri>/struts-btn-tags.tld</taglib-uri>
            <taglib-location>/WEB-INF/struts-btn-tags.tld</taglib-location>
        </taglib>
</jsp-config>

 

JSP中引用级调用方式:

引用,其中的uri为tld文件中定义的uri地址:

<%@ taglib uri="/struts-btn-tags" prefix="btn"%>


调用方式:

<!-- 自定义按钮,判断是否具有该按钮权限,如果有则显示,没有就不显示 -->
<btn:b type="button" uri="/user/updateInfo.action" clazz="updateInfo" value="修改"></btn:b>

到这里就基本上结束了,其中传递的uri将在后台业务逻辑那一块去做权限的查询,查询是否具有该权限,如果有,则输入一个button,没有则不错处理

在项目的其他地方,如果需要对<a></a>标签做权限判定也是差不多的,将来在在需要的判断按钮权限的地方用自定义的标签来实现一个按钮就能够精确到页面的每个按钮级的权限控制了,当然,按钮的权限无论是通过表单提交,还是js事件跳转,最终肯定会有一个请求,而那个请求就是我们的权限路径了,这个权限路径是需要本来就存在权限表里面的,然后给当前用户所属的角色授予权限

 

写的不是很清楚,如果有需要的朋友可以回复我。。

 

 

posted @ 2013-12-18 20:35  离尘  阅读(616)  评论(0)    收藏  举报