Shiro快速入門 —— 2.攔截器

本系列博文目錄:http://www.javashuo.com/article/p-ewndobct-kn.htmljava

 

ShiroFilter攔截器是整個Shiro的入口,用於攔截須要安全控制的請求並進行處理。ajax

shiro封裝了不少不一樣用途的攔截器,這裏只介紹幾個比較經常使用的攔截器,更詳細介紹能夠參考博文spring

《第八章 攔截器機制——跟我學Shiro》:http://jinnianshilongnian.iteye.com/blog/2025656安全

 

登陸攔截器(FormAuthenticationFilter)

因爲此攔截器常常須要繼承並重寫裏面的方法,來擴展本身的登陸攔截規則,因此會進行詳細介紹。app

 

等錄攔截器主要有兩個做用框架

一、攔截登陸表單提交的路徑(在攔截器工廠中配置)。jsp

    建立登陸認證所須要的Token令牌,並進入登陸認證流程。ide

二、攔截要求登陸才能夠訪問的路徑時(在攔截規則中配置)。url

    若是已經登陸則直接進入到要訪問路徑,若是未登陸則訪問被拒絕並跳轉到登陸頁。spa

 

方法介紹

createToken():

此方法用於建立登陸認證令牌,令牌內存儲了登陸認證時所需的數據。當咱們須要擴展shiro原有令牌的時候會重寫此方法,將擴展的令牌字段存入令牌。最典型的例子就是在令牌中增長了驗證碼字段。(令牌會在其餘章節另做介紹)

/**
     * 建立Token
     */
    @Override
    protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
        String username = getUsername(request);//獲取用戶名 表單name:username
        String password = getPassword(request);//獲取密碼 表單name:password
        boolean rememberMe = isRememberMe(request);//獲取是否記住我 表單name:rememberMe
        String captchaId = WebUtils.getCleanParam(request, "captchaId");//獲取驗證碼id
        String captcha = WebUtils.getCleanParam(request, "captcha");//獲取用戶輸入的驗證碼字符

        return new CaptchaAuthenticationToken(username, password,captchaId, captcha, rememberMe);//存入本身定義的包含驗證碼的Token
    }

 

onLoginSuccess():

登陸認證成功後的行爲。此方法只有在進行登陸認證成功後訪問一次。以後再訪問頁面時不會調用此方法。

 

onAccessDenied():

訪問被拒絕後的行爲。在攔截規則中指定須要登錄後才能訪問的路徑,若是沒有登陸則認爲訪問被拒絕。

此方法處理訪問被拒絕後的邏輯,最多見的就是對於ajax訪問拒絕的特殊處理。

此方法處理完成後,默認行爲會跳轉到登陸頁(能夠在攔截器工廠中配置 或 setLoginUrl方法設置登錄頁)。

這裏要注意若是是登陸操做,攔截器會先攔截並斷定爲拒絕訪問進入到此方法,而後再去進行建立Token和登陸認證等操做。

 

setLoginUrl():

設置登錄頁路徑。默認/login.jsp,能夠在攔截器工廠中配置 或 使用此方法重置。

訪問被拒絕時咱們可使用此方法返回到其餘登錄頁面,而不是以前的登陸頁。

@Override
    protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
        setLoginUrl("/otherlLogin");
        return super.onAccessDenied(servletRequest, servletResponse);
    }

 

getUsername():

得到登錄用戶名。表單name值必須是username。

getPassword():

得到登錄密碼。表單name值必須是password。

isRememberMe():

得到是否記住我。表單name值必須是rememberMe。

 

攔截器工廠類(ShiroFilterFactoryBean)

這個類用於spring框架中配置過濾器。

經過此工廠類能夠很方便的配置攔截器的各類基本屬性。

方法:

setSecurityManager:

必輸。注入一個SecurityManager類,SecurityManager負責管理整個shiro核心驗證功能。

 

setLoginUrl:

配置登陸頁路徑。這是一個很是方便的用法,咱們不須要在攔截器中來定義他。

這裏須要注意登陸頁即便不配置攔截規則也必定會被authc攔截。

在這有一個事情比較坑,setLoginUrl所配置的路徑便是頁面的訪問路徑,同時又是登錄表單提交的路徑。頁面訪問使用的是GET方式提交,表單使用的是POST方式提交。

/**
     * LoginController中的內容
     */

    //根路徑
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String loginForm() {
        return "redirect:login";
    }

    //登陸頁面
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String loginInput(@ModelAttribute("message") String message) {
        //判斷是否已經登陸 或 是否已經記住我
        if (SecurityUtils.getSubject().isAuthenticated() || SecurityUtils.getSubject().isRemembered()) {
            return "redirect:/home";
        } else {
            return "login";
        }
    }

    //登陸表單提交
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String login(HttpServletRequest request, RedirectAttributes redirectAttributes) {
       //登陸認證邏輯
    }

在這裏說明一下若是不一致致使的現象

若是隻配了頁面的訪問路徑則,登陸時將不會觸發shiro登陸攔截器。

若是隻配了登錄表單提交的路徑則,攔截器判斷爲未登陸時將沒法回到登陸頁面。

 

setSuccessUrl:

配置登陸成功頁路徑。這是一個很是方便的用法,咱們不須要在攔截器中來定義他。

 

setUnauthorizedUrl:

配置沒有權限跳轉的頁面。這是一個很是方便的用法,咱們不須要在攔截器中來定義他。

 

setFilterChainDefinitionMap:

設置攔截規則。攔截規則是經過一個Map進行導入的。

攔截規則寫法詳見「攔截規則」部分。

 

setFilters:

用於注入本身實現的攔截器類。自定義攔截器通常是繼承了shiro原有攔截器並重寫了部分方法。

 

一個spring boot配置文件中攔截器工廠類的例子:

/**
     * 得到攔截器工廠類
     */
    @Bean (name = "authenticationFilter")
    public AuthenticationFilter authenticationFilter() {
        return new AuthenticationFilter();
    }
    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager,AuthenticationFilter authenticationFilter) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);//設置SecurityManager,必輸
        shiroFilterFactoryBean.setLoginUrl("/login");//配置登陸路徑(登陸頁的路徑和表單提交的路徑必須是同一個,頁面的GET方式,表單的POST方式)
        shiroFilterFactoryBean.setSuccessUrl("/home");//配置登陸成功頁路徑
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");//配置沒有權限跳轉的頁面

        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
        filterChainDefinitionMap.put("/", "anon"); //無需登陸認證和受權就可訪問的路徑使用anon攔截器
        filterChainDefinitionMap.put("/home/**", "user");//須要登陸認證的路徑使用authc或user攔截器
        filterChainDefinitionMap.put("/user/**", "user,perms[user-jurisdiction]");//須要權限受權的路徑使用perms攔截器
        filterChainDefinitionMap.put("/admin/**", "user,perms[admin-jurisdiction]");//authc和perms攔截器可同時使用
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);//設置攔截規則

        Map<String, Filter> map = new HashMap<String, Filter>();
        map.put("authc", authenticationFilter);//自定義攔截器覆蓋了FormAuthenticationFilter登陸攔截器所用的攔截器名authc
        shiroFilterFactoryBean.setFilters(map);//添加自定義攔截器

        return shiroFilterFactoryBean;
    }

 

攔截規則寫法

攔截規則使用Map<String, String>將路徑與攔截器的映射關係進行匹配。

形式如:

Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
filterChainDefinitionMap.put("<攔截路徑>", "<攔截器名稱>");

<攔截器路徑>

攔截器路徑是一個從根路徑開始的url,並支持通配符。

登陸頁即便不配置也必定會被authc攔截。

<攔截器名稱>

是shiro內置攔截器的名稱,也能夠本身實現攔截器爲其定義名稱。

anon - 無需登陸認證和受權就可訪問的路徑使用anon攔截器

authc - 須要登陸認證的路徑使用authc攔截器

user - 用戶攔截器,用戶已經登陸認證 或 已經記住我 的均可以經過。

(user攔截器會自動調用authc 攔截器,因此若是要使用記住我功能只配置user便可)

perms[role_name] - 須要權限驗證的路徑使用perms攔截器。中括號內爲權限名稱列表。

 

多個攔截器能夠混合使用用逗號分隔

例子:

Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
filterChainDefinitionMap.put("/", "anon"); //無需登陸認證和受權就可訪問的路徑使用anon攔截器
filterChainDefinitionMap.put("/home/**", "user");//須要登陸認證的路徑使用authc或user攔截器
filterChainDefinitionMap.put("/user/**", "user,perms[user-jurisdiction]");//須要權限受權的路徑使用perms攔截器
filterChainDefinitionMap.put("/admin/**", "user,perms[admin-jurisdiction]");//authc和perms攔截器可同時使用
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);//設置攔截規則
相關文章
相關標籤/搜索