shiro与spring集成

来源:互联网 发布:最好的视频会议软件 编辑:程序博客网 时间:2024/05/18 12:37

Shiro 提供了与 Web 集成的支持,其通过一个ShiroFilter 入口来拦截需要安全控制的URL,然后进行相应的控制
ShiroFilter 类似于如 Strut2/SpringMVC 这种web 框架的前端控制器,是安全控制的入口点,其负责读取配置(如ini 配置文件),然后判断URL是否需要登录/权限等工作。
ShiroFilter
DelegatingFilterProxy 作用是自动到 Spring 容器查找名字为 shiroFilter(filter-name)的 bean 并把所有 Filter的操作委托给它。
在web.xml中配置

    <!--     1. 配置  Shiro 的 shiroFilter.      2. DelegatingFilterProxy 实际上是 Filter 的一个代理对象. 默认情况下, Spring 会到 IOC 容器中查找和     <filter-name> 对应的 filter bean. 也可以通过 targetBeanName 的初始化参数来配置 filter bean 的 id.     -->    <filter>        <filter-name>shiroFilter</filter-name>        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>        <init-param>            <param-name>targetFilterLifecycle</param-name>            <param-value>true</param-value>        </init-param>    </filter>    <filter-mapping>        <filter-name>shiroFilter</filter-name>        <url-pattern>/*</url-pattern>    </filter-mapping>

[urls] 部分的配置,其格式是: “ url=拦截器[参数],拦截器[参数]”;
如果当前请求的 url 匹配 [urls] 部分的某个 url 模式,将会执行其配置的拦截器。
anon(anonymous) 拦截器表示匿名访问(即不需要登录即可访问)
authc (authentication)拦截器表示需要身份认证通过后才能访问
URL 匹配模式
url 模式使用 Ant 风格模式
Ant 路径通配符支持 ?、 、 *,注意通配符匹配不包括目录分隔符“ /”:
-?:匹配一个字符,如 /admin? 将匹配 /admin1,但不
匹配 /admin 或 /admin/;
– *:匹配零个或多个字符串,如 /admin 将匹配 /admin、
/admin123,但不匹配 /admin/1;
:匹配路径中的零个或多个路径,如 /admin/ 将匹
配 /admin/a 或 /admin/a/b
URL 匹配顺序
URL 权限采取第一次匹配优先的方式,即从头开始使用第一个匹配的 url 模式对应的拦截器链。
如:
– /bb/**=filter1
– /bb/aa=filter2
– /**=filter3
– 如果请求的url是“ /bb/aa”,因为按照声明顺序进行匹配,那么将使用 filter1 进行拦截。
身份验证基本流程
1、首先调用 Subject.login(token) 进行登录,其会自动委托给SecurityManager
2、 SecurityManager 负责真正的身份验证逻辑;它会委托给Authenticator 进行身份验证;
3、 Authenticator 才是真正的身份验证者,Shiro API 中核心的身份认证入口点,此处可以自定义插入自己的实现;
4、 Authenticator 可能会委托给相应的 AuthenticationStrategy 进行多 Realm 身份验证,默认ModularRealmAuthenticator 会调用AuthenticationStrategy 进行多 Realm 身份验证;
5、 Authenticator 会把相应的 token 传入 Realm,从 Realm 获取身份验证信息,如果没有返回/抛出异常表示身份验证失败了。此处可以配置多个Realm,将按照相应的顺序及策略进行访问。
Realm
一般继承 AuthorizingRealm(授权)即可;其继承了AuthenticatingRealm(即身份验证),而且也间接继承了CachingRealm(带有缓存实现)。
Authenticator
Authenticator 的职责是验证用户帐号,是 Shiro API 中身份验证核心的入口点:如果验证成功,将返回AuthenticationInfo 验证信息;此信息中包含了身份及凭证;如果验证失败将抛出相应的 AuthenticationException 异常
SecurityManager 接口继承了 Authenticator,另外还有一个ModularRealmAuthenticator实现,其委托给多个Realm 进行
验证,验证规则通过 AuthenticationStrategy 接口指定
AuthenticationStrategy
AuthenticationStrategy 接口的默认实现:
FirstSuccessfulStrategy:只要有一个 Realm 验证成功即可,只返回第一个 Realm 身份验证成功的认证信息,其他的忽略;
AtLeastOneSuccessfulStrategy:只要有一个Realm验证成功即可,和FirstSuccessfulStrategy 不同,将返回所有Realm身份验证成功的认证信息;
AllSuccessfulStrategy:所有Realm验证成功才算成功,且返回所有Realm身份验证成功的认证信息,如果有一个失败就失败了。
ModularRealmAuthenticator 默认是 AtLeastOneSuccessfulStrategy策略
默认拦截器
Shiro 内置了很多默认的拦截器,比如身份验证、授权等相关的。默认拦截器可以参考org.apache.shiro.web.filter.mgt.DefaultFilter中的枚举拦截器:
身份验证相关的
这里写图片描述
授权相关的
这里写图片描述
Permissions
规则:资源标识符:操作:对象实例 ID
即对哪个资源的哪个实例可以进行什么操作. 其默认支持通配符权限字符串,: 表示资源/操作/实例的分割;, 表示操作的分割,* 表示任意资源/操作/实例。
多层次管理:
– 例如:user:query、 user:edit
– 冒号是一个特殊字符,它用来分隔权限字符串的下一部件:第一部分是权限被操作的领域(打印机),第二部分是被执行的操作。
– 多个值:每个部件能够保护多个值。因此,除了授予用户 user:query和 user:edit 权限外,也可以简单地授予他们一个:user:query, edit
– 还可以用 * 号代替所有的值,如:user:* , 也可以写:*:query,表示某个用户在所有的领域都有 query 的权限
Shiro 的 Permissions
实例级访问控制
– 这种情况通常会使用三个部件:域、操作、被付诸实施的实例。 如:user:edit:manager
– 也可以使用通配符来定义,如:user:edit:、 user::、user::manager
– 部分省略通配符:缺少的部件意味着用户可以访问所有与之匹配的值,比如:user:edit 等价于 user:edit :*、
user 等价于 user::
– 注意:通配符只能从字符串的结尾处省略部件,也就是说 user:edit 并不等价于 user:*:edit
授权流程
流程如下:
• 1、首先调用 Subject.isPermitted*/hasRole* 接口,其会委托给SecurityManager,而 SecurityManager 接着会委托给 Authorizer;
• 2、 Authorizer是真正的授权者,如果调用如isPermitted(“ user:view”),其首先会通过PermissionResolver 把字符串转换成相应的 Permission 实例;
• 3、在进行授权之前,其会调用相应的 Realm 获取 Subject 相应的角色/权限用于匹配传入的角色/权限;
• 4、 Authorizer 会判断 Realm 的角色/权限是否和传入的匹配,如果有多个Realm,会委托给 ModularRealmAuthorizer 进行循环判断,如果匹配如 isPermitted*/hasRole* 会返回true,否则返回false表示授权失败。
ModularRealmAuthorizer
• ModularRealmAuthorizer 进行多 Realm 匹配流程:
– 1、首先检查相应的 Realm 是否实现了实现了Authorizer;
– 2、如果实现了 Authorizer,那么接着调用其相应的isPermitted*/hasRole* 接口进行匹配;
– 3、如果有一个Realm匹配那么将返回 true,否则返回 false。
权限注解
• @RequiresAuthentication:表示当前Subject已经通过login进行了身份验证;即 Subject. isAuthenticated() 返回 true
• @RequiresUser:表示当前 Subject 已经身份验证或者通过记住我登录的。
• @RequiresGuest:表示当前Subject没有身份验证或通过记住我登录过,即是游客身份。
• @RequiresRoles(value={“admin”, “user”}, logical=Logical.AND):表示当前 Subject 需要角色 admin 和user
• @RequiresPermissions (value={“ user:a”, “ user:b”},logical= Logical.OR):表示当前 Subject 需要权限 user:a 或
user:b。
自定义拦截器
通过自定义拦截器可以扩展功能,例如:动态url-角色/权限访问控制的实现、 根据 Subject 身份信息获取用户信息
绑定到 Request(即设置通用数据)、验证码验证、 在线用户信息的保存等
RememberMe
Shiro 提供了记住我(RememberMe)的功能,比如访问如淘宝等一些网站时,关闭了浏览器,下次再打开时还是能记住你是谁,下次访问时无需再登录即可访问,基本流程如下:
• 1、首先在登录页面选中 RememberMe 然后登录成功;如果是浏览器登录,一般会把 RememberMe 的Cookie 写到客户端并保存下来;
• 2、关闭浏览器再重新打开;会发现浏览器还是记住你的;
• 3、访问一般的网页服务器端还是知道你是谁,且能正常访问;
• 4、但是比如我们访问淘宝时,如果要查看我的订单或进行支付时,此时还是需要再进行身份认证的,以确保当前用户还是你。
认证和记住我
• subject.isAuthenticated() 表示用户进行了身份验证登录的,即使有 Subject.login 进行了登录;
• subject.isRemembered():表示用户是通过记住我登录的,此时可能并不是真正的你(如你的朋友使用你的电脑,或者
你的cookie 被窃取)在访问的两者二选一,即 subject.isAuthenticated()==true,则subject.isRemembered()==false;反之一样。

• 访问一般网页:如个人在主页之类的,我们使用user 拦截器即可,user 拦截器只要用户登录
(isRemembered() || isAuthenticated())过即可访问成功;
• 访问特殊网页:如我的订单,提交订单页面,我们使用authc 拦截器即可,authc 拦截器会判断用户是否是通过
Subject.login(isAuthenticated()==true)登录的,如果是才放行,否则会跳转到登录页面叫你重新登录。
实现
如果要自己做RememeberMe,需要在登录之前这样创建Token:UsernamePasswordToken(用户名,密码,是否记住我),且调用UsernamePasswordToken 的:token.setRememberMe(true); 方法

原创粉丝点击