Shiro 集成 Spring 之過濾器

前言

在之前 Shiro 集成 Spring 這一章中我們簡單使用了 shiroFilter 中的 filterChainDefinitions 來做 認證授權 的攔截,其實還有許多過濾器,可以做各種各樣的攔截,並且 Shiro 還提供了接口來讓我們自定義過濾器。

身份認證相關

anon

例:/admins/**=anon,沒有參數,表示可以匿名使用。

authc

例:/admins/user/**=authc,沒有參數,表示需要認證(登錄)才能使用。

authcBasic

例:/admins/user/**=authcBasic,沒有參數,表示 httpBasic 認證。

user

例:/admins/user/**=user ,沒有參數,表示必須存在用戶(不一定已通過認證),只要曾被 Shiro 記住過登錄狀態的用戶就可以正常發起請求,比如 rememberMe)。

logout

例:/logout=logout,沒有參數,註銷當前登陸用戶,成功後會重定向地址到 /

授權相關

roles

例:/admins/user/**=roles[admin],參數可以寫多個,用逗號分割,當有多個參數時,例如 admins/user/**=roles[admin, guest],每個參數通過纔算通過,相當於 hasAllRoles() 方法。

perms

例:/admins/user/**=perms[user:add:*],參數可以寫多個,用逗號分割,如:/admins/user/**=perms[user:add:*, user:modify:*],當有多個參數時必須每個參數都通過才通過,想當於 isPermitedAll() 方法。

port

例: /admins/user/**=port[8081],單個參數,當請求的 url 的端口不是 8081 時重定向到 schemal://hostName:8081?queryString, 也就是說,除了端口,其他東西都會保留。

rest

例:/admins/user/**=rest[user],根據請求的方法,相當於 /admins/user/**=perms[user:method],其中method爲post,get,delete等。

ssl

例:/admins/user/**=ssl 沒有參數,表示安全的 url 請求,協議爲 https,其實也等同於 /admin/user/**=port[443],即重定向到 443 端口。

自定義過濾器

roles 過濾器爲例:/admin/page1= roles["admin, user"] ,表示 /admin/page1 這個頁面必須需要用戶同時具備 adminuser 角色纔可訪問。

我們開發一個自定義的過濾器,判定需要 adminuser 可訪問。

package im.zhaojun.filter;

import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class AnyRolesFilter extends AuthorizationFilter {

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        Subject subject = this.getSubject(request, response);
        String[] rolesArray = (String[]) ((String[]) mappedValue);
        if (rolesArray != null && rolesArray.length != 0) {
            for (String role : rolesArray) {
                if (subject.hasRole(role)) {
                    return true;
                }
            }
        } else {
            return true;
        }
        return false;
    }
}

注:這裏用到了 ServletRequestServletResponse 類,所以還需要導入相應的庫:

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.0.1</version>
    <scope>provided</scope>
</dependency>

然後將其配置到 IOC 容器中:

<bean id="anyRolesFilter" class="im.zhaojun.filter.AnyRolesFilter"/>

最後爲其分配別名,並添加到過濾器鏈中:

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!-- 略 -->
        <property name="filterChainDefinitions">
            <value>
                /login.jsp = anon
                /login = anon
                /user.jsp = anyRoles[user, admin]
                /userList.jsp = perms[select:delete]
                /logout = logout
                /** = authc
            </value>
        </property>
        <property name="filters">
            <map>
                <entry key="anyRoles" value-ref="anyRolesFilter"/>
            </map>
        </property>
    </bean>

我們分別將 /user.jsp 設爲 roles[user, admin]anyRoles[user, admin]

目前 Relam 中的用戶 zhao - 123456 僅具備 user 角色,所以可以分別測試出,anyRoles 過濾的頁面可以正常訪問,而 roles 過濾器的內容因未同時具備 useradmin 角色而被攔截,跳轉到未授權頁面。

通配符

上面的示例中,我們還用到了 ** 做通配符,其實還有幾個通配符:

?:匹配一個字符,如 /admin? 可以匹配 /admin1/admin2,但不能匹配 /admin

*:匹配零個或一個或多個字符,如 /admin* 可以匹配 /admin/admin1/admin123,但不能匹配 /admin/123

**:匹配零個或多個路徑,如 /admin/** 可以匹配 /admin/admin/a/b/c

本章代碼地址 : https://github.com/zhaojun1998/Premission-Study/tree/master/Permission-Shiro-07/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章