自己動手實現簡單權限控制


   最近接手一小型私活,用戶量封頂上千,工期預期的也相對寬松,權限控制當然是必不可少。

   web 權限控制,很多項目會引入 shiro/spring-security。

   shiro/spring-security 繼承 servlet-->filter抽象接口,運用合適的設計模式,

   通過攔截客戶端請求,來實現各個角色對系統資源的訪問權限。

   一時興起,有了自己實現權限控制的想法,遂有此文,如果你用膩了 shiro/spring-security,不妨來和我一起完善它。

   本文只做拋磚引玉之用,重點在思路,具體項目具體編程語言請自行拿捏。

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

   Shiro 中定義攔截過濾鏈,可以很簡單實現上圖中的想法,像下面這種姿勢(但咱的目的是自己動手)。

  <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        ............
        <!-- 過濾鏈定義 -->
        <property name="filterChainDefinitions">
            <value>
                <!--anno:AnonymousFilter 不需要任何權限即可訪問-->
                /login.jsp* = anon
                /login.do* = anon
                <!--authc:FormAuthenticationFilter 表單驗證權限-->
                /pages/* = authc
                /index.jsp* = authc
                <!--perms:PermissionsAuthorizationFilter 指定授權訪問-->
                /role/edit/* = perms[role:edit]
                /role/save = perms[role:edit]
                /role/list = perms[role:view]
            </value>
        </property>
    </bean>

   想法大致和 shiro/spring-security 相同,實現 Filter 接口攔截客戶端的對應請求。

   比較有意思的部分,首先你得確定該 Filter 需要攔截什么的請求,服務? 靜態頁面 ? 交互腳本?網頁樣式?圖片?

   當然項目需要有良好的命名規范,無論是 restful 風格或傳統風格。規范項目中的請求 URL 或添加特定的后綴。web.xml 配置比如像下面。

    <filter>
        <filter-name>simpleAuthFilter</filter-name>
        <filter-class>com.rambo.sad.SimpleAuthFilter</filter-class>
        <init-param>
            <param-name>defaultPage</param-name>
            <param-value>/view/login.jsp</param-value>
        </init-param>
        <init-param>
            <param-name>freeServices</param-name>
            <param-value>
                /view/login.jsp,login.do <!--登錄相關-->
            </param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>simpleAuthFilter</filter-name>
        <url-pattern>*.jsp</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>simpleAuthFilter</filter-name>
        <url-pattern>*.do</url-pattern>
    </filter-mapping>

   其次你需要確定該本次請求是否有訪問該資源的權限,我項目中確定邏輯比較簡單,畢竟千人系統。

   將登錄頁面和登錄請求做為 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方法邏輯像下面。

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws Exception{
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpSession session = request.getSession(false);
if ((session == null || session.getAttribute("user") == null) && !isFreeService(request.getRequestURI())) { request.setAttribute("SESSIONFILTER_MSG", "LOGIN_TIMEOUT"); request.getRequestDispatcher(defaultPage).forward(servletRequest, servletResponse);return; } filterChain.doFilter(servletRequest, servletResponse); }

   到此,整個設計思路已敘述清楚,只需自己實現一個 Filter 即可,騷年是不是很簡單?

   個人認為其中的可擴展點還很多,做通用並且好用還是有難度的,比如詳細的角色訪問策略,制定合理的設計模式。

   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM