美文网首页
Shiro4-基于url拦截-用户授权实现

Shiro4-基于url拦截-用户授权实现

作者: 我相信你爱过gg | 来源:发表于2017-05-17 21:27 被阅读1632次

    在上一个笔记中我们实现了用户认证,那么接下来我们实现用户授权,看一下流程图.

    这个流程图就是上一个笔记中的图, 我截取的部分就是用户授权的流程

    在流程图中我们看到有一个授权过滤器拦截获取访问URL,所以我们就需要创建这个拦截器,然后在拦截器中,进行下面流程操作.

    我们可以看到有一个URL是否公开地址这个与我们上一个笔记中的公开地址是不一样的.

    这个配置文件的所用是,让授权过滤器不对配置文件中的URL分配访问权限,可以允许直接访问.

    可能有人会想在做用户认证的时候有一个公开地址,用户授权的时候也有一个公开地址,这两个公开地址不能使用同一个吗?
    答:用户认证时候的那个公开地址,就是我们没有用户认证通过就能访问的地址,比如: 系统登录的URL.
    而这个用户授权的公开地址是 我们已经通过用户认证了,进入后台,但是由于不同角色登录系统后有不同的权限,所以我们需要做一些限制,哪些权限能访问哪些URL地址.而所有权限都能访问的地址,我们就将这些地址放到公开URL配置文件中.

    创建公开地址配置文件

    我们创建一个名为commonURL.properties的文件来存放我们的URL公开地址.
    我们在这个文件中配置两条数据

    login.action=退出
    

    如果用户访问的URL在公共访问地址中那么就可以直接访问,如果不在就会判断用户访问的这个URL在不在他的权限中,如果在那么可以访问,如果不在就提示无权操作.

    但是这里要注意, 我们的权限是存在数据库中,而授权过滤器每次都要拦截用户访问的URL进行判断,那么就意味着我们每次都要操作数据库,但是如果我们每次都去操作数据库这也就意味着会降低系统性能.

    所以我们的解决方案就是,在用户认证通过后将权限取出,放到session中或缓存中.

    获取用户权限范围的URL与用户菜单

    思路: 在用户认证通过后,根据用户id从数据库获取用户权限范围的url,然后将url的集合存储在session中.

    SQL语句

        SELECT 
          * 
        FROM
          sys_permission 
        WHERE TYPE = #{type}
          AND id IN 
          (SELECT 
            sys_permission_id 
          FROM
            sys_role_permission 
          WHERE sys_role_id IN 
            (SELECT 
              sys_role_id 
            FROM
              sys_user_role 
            WHERE sys_user_id = #{id}))
    

    参数 type: 如果要查询权限就写permission 如果要查询菜单就写menu
    参数 id: 用户id

    然后在service中查询出来,将菜单和url放入你创建的ActiveUser对象中,再将这个对象放入session中.

    上面的这些操作就是取出我们要的数据,并且放到session中了,接下来就是判断了.

    最终代码

        //在执行handler之前来执行的
        //用于用户认证校验、用户权限校验
        @Override
        public boolean preHandle(HttpServletRequest request,
                HttpServletResponse response, Object handler) throws Exception {
            
            //得到请求的url
            String url = request.getRequestURI();
            
            //判断是否是公开 地址
            //实际开发中需要公开 地址配置在配置文件中
            //从配置中取逆名访问url
            
            List<String> open_urls = ResourcesUtil.gekeyList("anonymousURL");
            //遍历公开 地址,如果是公开 地址则放行
            for(String open_url:open_urls){
                if(url.indexOf(open_url)>=0){
                    //如果是公开 地址则放行
                    return true;
                }
            }
            
            //从配置文件中获取公共访问地址
            List<String> common_urls = ResourcesUtil.gekeyList("commonURL");
            //遍历公用 地址,如果是公用 地址则放行
            for(String common_url:common_urls){
                if(url.indexOf(common_url)>=0){
                    //如果是公开 地址则放行
                    return true;
                }
            }
            
            //获取session
            HttpSession session = request.getSession();
            ActiveUser activeUser = (ActiveUser) session.getAttribute("activeUser");
            //从session中取权限范围的url
            List<SysPermission> permissions = activeUser.getPermissions();
            for(SysPermission sysPermission:permissions){
                //权限的url
                String permission_url = sysPermission.getUrl();
                if(url.indexOf(permission_url)>=0){
                    //如果是权限的url 地址则放行
                    return true;
                }
            }
            
            //执行到这里拦截,跳转到无权访问的提示页面
            request.getRequestDispatcher("/WEB-INF/jsp/refuse.jsp").forward(request, response);
            
            //如果返回false表示拦截不继续执行handler,如果返回true表示放行
            return false;
        }
    

    配置授权拦截器

    注意:将授权连接器配置在用户认证拦截器的下边.

        <!--拦截器 -->
        <mvc:interceptors>
    
            <mvc:interceptor>
                <!-- 用户认证拦截 -->
                <mvc:mapping path="/**" />
                <bean class="cn.xxx.interceptor.LoginInterceptor"></bean>
            </mvc:interceptor>
            <mvc:interceptor>
                <!-- 授权拦截 -->
                <mvc:mapping path="/**" />
                <bean class="cn.xxx.interceptor.PermissionInterceptor"></bean>
            </mvc:interceptor>
        </mvc:interceptors>
    
    

    这样就做完了,但是这种方式有好处也有坏处
    好处:实现起来比较简单,不依赖框架,使用web提供的filter就可以实现.
    坏处:需要将所有的url全部配置起来(放入数据库和公共文件中),这样做有些繁琐,不容易维护.


    相关文章

      网友评论

          本文标题:Shiro4-基于url拦截-用户授权实现

          本文链接:https://www.haomeiwen.com/subject/gpbdxxtx.html