Loading... ## 前言 在之前 [Shiro 集成 Spring](http://www.zhaojun.im/shiro-05/) 这一章中我们简单使用了 `shiroFilter` 中的 `filterChainDefinitions` 来做 `认证` 和 `授权` 的拦截,其实还有许多过滤器,可以做各种各样的拦截,并且 Shiro 还提供了接口来让我们自定义过滤器。 <!--more--> ## 身份认证相关 ### anon 例:`/admins/**=anon`,没有参数,表示可以匿名使用。 ### authc 例:`/admins/user/**=authc`,没有参数,表示需要认证(登录)才能使用。 ### authcBasic 例:`/admins/user/**=authcBasic`,没有参数,表示 httpBasic 认证。 ### user 例:`/admins/user/**=user` ,没有参数,表示用户已登陆或 `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` 这个页面必须需要用户同时具备 `admin` 与 `user` 角色才可访问。 我们开发一个自定义的过滤器,判定需要 `admin` 或 `user` 可访问。 ```java 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; } } ``` 注:这里用到了 `ServletRequest` 和 `ServletResponse` 类,所以还需要导入相应的库: ```xml <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> <scope>provided</scope> </dependency> ``` 然后将其配置到 IOC 容器中: ```java <bean id="anyRolesFilter" class="im.zhaojun.filter.AnyRolesFilter"/> ``` 最后为其分配别名,并添加到过滤器链中: ```xml <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` 过滤器的内容因未同时具备 `user` 与 `admin` 角色而被拦截,跳转到未授权页面。 ## 通配符 上面的示例中,我们还用到了 `**` 做通配符,其实还有几个通配符: `?`:匹配一个**字符**,如 `/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/ 最后修改:2022 年 05 月 02 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请我喝杯咖啡吧。