web 权限控制,很多项目会引入 shiro/spring-security。

   shiro/spring-security 继承 servlet-->filter抽象接口,运用合适的设计模式,

   通过拦截客户端请求,来实现各个角色对系统资源的访问权限。

   一时兴起,有了自己实现权限控制的想法,遂有此文,如果你用腻了 shiro/spring-security,不妨来和我一起完善它。

   本文只做抛砖引玉之用,重点在思路,具体项目具体编程语言请自行拿捏。

   Git Demo:https://git.oschina.net/LanboEx/simple-auth-demo

   Shiro 中定义拦截过滤链,可以很简单实现上图中的想法,像下面这种姿势(但咱的目的是自己动手)。

  
        ............        
        
            
                
                /login.jsp* = anon
                /login.do* = anon                
                /pages/* = authc
                /index.jsp* = authc                
                /role/edit/* = perms[role:edit]
                /role/save = perms[role:edit]
                /role/list = perms[role:view]            
        
    

   想法大致和 shiro/spring-security 相同,实现 Filter 接口拦截客户端的对应请求。

   比较有意思的部分,首先你得确定该 Filter 需要拦截什么的请求,服务? 静态页面 ? 交互脚本?网页样式?图片?

   当然项目需要有良好的命名规范,无论是 restful 风格或传统风格。规范项目中的请求 URL 或添加特定的后缀。web.xml 配置比如像下面。

    
        simpleAuthFilter
        com.rambo.sad.SimpleAuthFilter
        
            defaultPage
            /view/login.jsp
        
        
            freeServices
            
                /view/login.jsp,login.do 
            
        
    
    
        simpleAuthFilter
        *.jsp
    
    
        simpleAuthFilter
        *.do
    

   其次你需要确定该本次请求是否有访问该资源的权限,我项目中确定逻辑比较简单,毕竟千人系统。

   将登录页面和登录请求做为 FreeService ,也就是暴露在系统外的资源,登录时在 Session 中放置对应登录对象 PO。

   既方便系统内的相应展示,也可做为用户是否登录的凭证,比如登录服务逻辑像下面。

 @RequestMapping("/login.do")    public String login(HttpSession httpSession, UserPO userPO) {
        logger.info("login name:" + userPO.getName() + ",pwd:" + userPO.getPasswd());        //一些必要的系统前置工作.....
        httpSession.setAttribute("user", userPO);        return "success";
    }

   当然也可以引入数据库设计,划分用户角色来制定详细的访问策略。

   最后继承 Filter 接口拦截每次客户端请求,来决定是否能获取到对应的系统资源。

   defaultPage 为权限不足时默认跳转的页面,比如 Filter doFilter方法逻辑像下面。

      doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) == request.getSession( ((session ==  || session.getAttribute("user") == ) && !"SESSIONFILTER_MSG", "LOGIN_TIMEOUT"