zoukankan      html  css  js  c++  java
  • 一种基于annotation的Spring-mvc权限控制方法

    简介

    本文介绍一种采用annotation来对spring-mvc进行权限控制的方法. 通过枚举类来定义权限项. 将annotation标注到需要控制权限的spring-mvc方法上. 然后,在spring-mvc中定义全局过滤器, 过滤所有spring-mvc方法, 查看方法上的权限annotation信息, 以此对权限进行控制.
    程序源代码: https://github.com/eagle0445/sample/

    优点

    编写比较方便, 在需要控制权限的方法上进行annotation的标注即可, ide能够对annotation进行识别支持. 查看权限配置比较方便, 因为annotation就在方法上, 不用去其他地方翻看. 实现方式比较简单.

    具体实现

    1.建立权限枚举类

    建立权限枚举类型, 用于描述权限的种类, 包含了权限的名称. 每个枚举值中包含了权限中文名称和权限索引值(即权限位). (思考:是否可以直接用中文名称作为枚举值的名称,我在其他程序已经用了中文枚举名称了,暂时没有遇到问题)

    <!-- lang: java -->
    public enum AuthorityType{
    // 包含了枚举的中文名称, 枚举的索引值
    WORKER("增删改查员工", 1),
    
    SALES_ORDER_CREATE("创建订单", 6), 
    SALES_ORDER_FIND("查看订单", 7),
    SALES_ORDER_MODIFY("修改订单", 8),
    SALES_ORDER_DELETE("删除订单", 9),
    ;
    private String name;
    private int index;
    
    private AuthorityType(String name, int index) {
        this.name = name;
        this.index = index;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getIndex() {
        return index;
    }
    public void setIndex(int index) {
        this.index = index;
    }
    }
    

    2.登录方式的枚举类

    登录方式的枚举类, page代表传统登录页面, json表示ajax的登录

    <!-- lang: java -->
    public enum ResultTypeEnum {
    //整页刷新
    page, 
    //json数据
    json
    }

    3.建立表示权限annotation类

    建立annotation类, 用于标注到需要权限验证的地方

    <!-- lang: java -->
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface FireAuthority {
        AuthorityType[] authorityTypes();
        ResultTypeEnum resultType() default ResultTypeEnum.page;
    }
    

    4.在user类中加入权限字段

    在user用户类中添加文本字段表示权限, 字段长度为250字符(因为mysql默认255个字符,可以代表250个权限应该够用了), 字符内容是0或者1. 1表示有权限, 0表示无权限. 提示: 对于用户的权限配置, 只要将对应的权限位设置为0或者1即可.

    <!-- lang: sql -->
        create table user (
            id integer not null auto_increment,
            name varchar(255),
            right_content varchar(255),
            primary key (id)
        ) type=InnoDB
    

    5.权限验证算法

    权限判断方法, 权限判断的实现算法, 用于判断是否有权限

    <!-- lang: java -->
    public class AuthorityHelper {
    
    /**
     * 判断是否有权限
     * @param akey  aString中位置的索引值,也就是权限位
     * @param aString  权限字段,比如 11010101011101
     * @return
     */
    public static boolean hasAuthority(int akey,String aString){
        return ConstanHelper.getAuthorityVaule(akey,rc);
        if(aString==null || "".equals(aString)){
            return false;
        }
    
        char value = aString.charAt(akey);
        if(value == '1'){
            return true;
        }
    
        return false;
    
    }
    
    }
    

    6.建立控制权限的interceptor类

    建立interceptor类, 用于过滤需要控制权限的方法.

    <!-- lang: java -->
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import java.net.URLEncoder;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.method.HandlerMethod;
    import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
    
    public class AuthorityAnnotationInterceptor extends HandlerInterceptorAdapter {
    
        final Logger logger = LoggerFactory.getLogger(getClass());
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            logger.debug("");
            HandlerMethod handler2=(HandlerMethod) handler;
            FireAuthority fireAuthority = handler2.getMethodAnnotation(FireAuthority.class);
    
            if(null == fireAuthority){
                //没有声明权限,放行
                return true;
            }
    
            logger.debug("fireAuthority", fireAuthority.toString());
    
            HttpSession session = request.getSession();
            Worker manager = (Worker)session.getAttribute(SessionHelper.WorkerHandler);
            boolean aflag = false;
    
            for(AuthorityType at:fireAuthority.authorityTypes()){
                if(AuthorityHelper.hasAuthority(at.getIndex(), manager.getRightContent())==true){
                    aflag = true;
                    break;
                }
            }
    
            if(false == aflag){
    
                if (fireAuthority.resultType() == ResultTypeEnum.page) {
                    //传统的登录页面                
                    StringBuilder sb = new StringBuilder();
                    sb.append(request.getContextPath());
                    sb.append("/oprst.jsp?oprst=false&opmsg=").append(URLEncoder.encode(ControllerProperty.NOT_HAVE_AUTHORITY,"utf-8"));
                    response.sendRedirect(sb.toString());
                } else if (fireAuthority.resultType() == ResultTypeEnum.json) {
                    //ajax类型的登录提示
                    response.setCharacterEncoding("utf-8");
                    response.setContentType("text/html;charset=UTF-8");
                    OutputStream out = response.getOutputStream();
                    PrintWriter pw = new PrintWriter(new OutputStreamWriter(out,"utf-8"));
                    pw.println("{"result":false,"code":12,"errorMessage":""+ControllerProperty.NOT_HAVE_AUTHORITY+""}");
                    pw.flush();
                    pw.close();
                }
    
                return false;
    
            }
            return true;
        }
    
    }
    

    7.配置interceptor类

    在spring-mvc中配置interceptor, 实现过滤.

    <!-- lang: xml -->
        <mvc:interceptors>
            <bean class="interceptor.AuthorityAnnotationInterceptor"></bean>
        </mvc:interceptors>
    

    8.标注需要控制权限的方法

    在需要控制访问的spring-mvc方法上面加上对应的标注.
    //方式一

    <!-- lang: java -->
    @FireAuthority(AuthorityType. SALES_ORDER_CREATE)
    @RequestMapping(value="/save.spr", method=RequestMethod.POST)
    public ModelAndView save(String  name) throws Exception {
        //some code
    }

    //方式二

    <!-- lang: java -->
    @FireAuthority(authorityTypes = {AuthorityType.SALES_ORDER_DELETE,AuthorityType.SALES_ORDER_CREATE})
        @RequestMapping(value="/save.spr", method=RequestMethod.POST)
        public ModelAndView save(String  name) throws Exception {
            //some code
        }

    //方式三

        <!-- lang: java -->
    @FireAuthority(authorityTypes = AuthorityType.SALES_ORDER_DELETE, resultType=ResultTypeEnum.page)
    @RequestMapping(value="/save.spr", method=RequestMethod.POST)
    public ModelAndView save(String  name) throws Exception {
        //some code
    }

    9.完成了

    ^_^

    后续

    还需要一套界面,以便进行用户权限的配置, 幸运的是本人已经实现了这一功能, 而代码相对比较简单, 将在后面的博客中进行详细解说.
    程序源代码: https://github.com/eagle0445/sample/

  • 相关阅读:
    Java实现 LeetCode 236 二叉树的最近公共祖先
    Java实现 LeetCode 236 二叉树的最近公共祖先
    Java实现 LeetCode 235 二叉搜索树的最近公共祖先
    Java实现 LeetCode 235 二叉搜索树的最近公共祖先
    Java实现 LeetCode 235 二叉搜索树的最近公共祖先
    Java实现蓝桥杯打印图形
    Java实现蓝桥杯打印图形
    Java实现蓝桥杯打印图形
    C++ int与string的转化
    C语言:将16进制字符串转化为int类型值
  • 原文地址:https://www.cnblogs.com/huaxingtianxia/p/5667517.html
Copyright © 2011-2022 走看看