shiro(3)-shiro核心
身份认证
身份认证分三个步骤
1)提交主题和凭据
2)进行身份认证
3)判断是通过,重新提交还是不通过
验证顺序
1)调用subject的login方法,提交主体和凭据。
2)得到对应操作的Security Manager
3)通过Sceurity Manager得到对应的Autherticator实例
4)根据配置策略查找对应的桥信息
5)通过桥信息到对应的配置处理进行身份验证
验证器
如果你想配置一个自定义的验证器
可以在配置文件中使用
[main] ... authenticator = com.foo.bar.CustomAuthenticator securityManager.authenticator = $authenticator |
配置策略信息
AtLeastOneSuccessfulStrategy 如果一个验证成功,则验证结果为成功
FirstSuccessfulStrategy 只有第一个成功,才算成功
AllSuccessfulStrategy 所有的都必须成功
对应的在配置文件中的策略使用如下
shiro.ini [main] ... authcStrategy = org.apache.shiro.authc.pam.FirstSuccessfulStrategy securityManager.authenticator.authenticationStrategy = $authcStrategy ... |
执行顺序
1)隐式顺序
blahRealm = com.company.blah.Realm ... fooRealm = com.company.foo.Realm ... barRealm = com.company.another.Realm |
按上下顺序执行
2)指定顺序
blahRealm = com.company.blah.Realm ... fooRealm = com.company.foo.Realm ... barRealm = com.company.another.Realm securityManager.realms = $fooRealm, $barRealm, $blahRealm ... |
按指定的顺序执行
授权
控制谁有权限访问应用程序
授权的几个要素:权限,角色和用户。
三种权限的判断方式
1)编程
角色判断
Subject currentUser = SecurityUtils.getSubject(); if (currentUser.hasRole( "administrator" )) { //show the admin button } else { //don't show the button? Grey it out? } |
hasRole(String roleName) 主题是否已分配给指定的角色
hasRoles(List<String> roleNames) 是否包含指定的角色
hasAllRoles(Collection<String> roleNames) 是否包含指定的所有角色
角色断言
Subject currentUser = SecurityUtils.getSubject(); //guarantee that the current user is a bank teller and //therefore allowed to open the account: currentUser.checkRole( "bankTeller" ); openBankAccount(); |
checkRole(String roleName) 断言是否是指定角色
checkRoles(Collection<String> roleNames) 断言是否包含以下角色
checkRoles(String... roleNames) 断言是否包含所有角色
如果判断指定用户是否有权限访问指定名称的打印机
那么就会用到下列几个方法
Permission printPermission = new PrinterPermission( "laserjet4400n" , "print" ); Subject currentUser = SecurityUtils.getSubject(); if (currentUser.isPermitted(printPermission)) { //show the Print button } else { //don't show the button? Grey it out? } |
isPermitted(Permission p) 判断主题是否允许执行一个动作
isPermitted(List<Permission> perms) 是否允许执行一组动作
isPermittedAll(Collection<Permission> perms) 是否允许执行所有动作
基于字符串的权限检查
Subject currentUser = SecurityUtils.getSubject(); if (currentUser.isPermitted( "printer:print:laserjet4400n" )) { //show the Print button } else { //don't show the button? Grey it out? } |
也可以如下使用
Subject currentUser = SecurityUtils.getSubject(); Permission p = new WildcardPermission( "printer:print:laserjet4400n" ); if (currentUser.isPermitted(p) { //show the Print button } else { //don't show the button? Grey it out? } |
权限断言类似于角色断言。
2)annocation方式
The RequiresAuthentication annotation
@RequiresAuthentication public void updateAccount(Account userAccount) { //this method will only be invoked by a //Subject that is guaranteed authenticated ... } |
等同于下述代码
public void updateAccount(Account userAccount) { if (!SecurityUtils.getSubject().isAuthenticated()) { throw new AuthorizationException(...); } //Subject is guaranteed authenticated here ... } |
The RequiresGuest annotation
@RequiresGuest public void signUp(User newUser) { //this method will only be invoked by a //Subject that is unknown/anonymous ... } |
等同于
public void signUp(User newUser) { Subject currentUser = SecurityUtils.getSubject(); PrincipalCollection principals = currentUser.getPrincipals(); if (principals != null && !principals.isEmpty()) { //known identity - not a guest: throw new AuthorizationException(...); } //Subject is guaranteed to be a 'guest' here ... } |
The RequiresPermissions annotation
@RequiresPermissions ( "account:create" ) public void createAccount(Account account) { //this method will only be invoked by a Subject //that is permitted to create an account ... } |
等同于
public void createAccount(Account account) { Subject currentUser = SecurityUtils.getSubject(); if (!subject.isPermitted( "account:create" )) { throw new AuthorizationException(...); } //Subject is guaranteed to be permitted here ... } |
The RequiresRoles permission
@RequiresRoles ( "administrator" ) public void deleteUser(User user) { //this method will only be invoked by an administrator ... } |
等同于
public void deleteUser(User user) { Subject currentUser = SecurityUtils.getSubject(); if (!subject.hasRole( "administrator" )) { throw new AuthorizationException(...); } //Subject is guaranteed to be an 'administrator' here ... } |
The RequiresUser annotation
@RequiresUser public void updateAccount(Account account) { //this method will only be invoked by a 'user' //i.e. a Subject with a known identity ... } |
等同于
public void updateAccount(Account account) { Subject currentUser = SecurityUtils.getSubject(); PrincipalCollection principals = currentUser.getPrincipals(); if (principals == null || principals.isEmpty()) { //no identity - they're anonymous, not allowed: throw new AuthorizationException(...); } //Subject is guaranteed to have a known identity here ... } |
授权顺序
1)应用程序调用主题,判断hasRole,isPermitted得到角色或者用户权限的列表。
2)组成对应的授权方法
3)协调如何授权
4)通过桥进行各种方式的授权
web应用
配置web.xml
<listener> <listener- class >org.apache.shiro.web.env.EnvironmentLoaderListener</listener- class > </listener> ... <filter> <filter-name>ShiroFilter</filter-name> <filter- class >org.apache.shiro.web.servlet.ShiroFilter</filter- class > </filter> <filter-mapping> <filter-name>ShiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> |
如果你愿意你可以自定义一个web应用
<context-param> <param-name>shiroEnvironmentClass</param-name> <param-value>com.foo.bar.shiro.MyWebEnvironment</param-value> </context-param> |
如果你想改变shiro.ini的位置,那么你可以指定
<context-param> <param-name>shiroConfigLocations</param-name> <param-value>YOUR_RESOURCE_LOCATION_HERE</param-value> </context-param> |
shiro.ini中的[urls]配置
例如:
... [urls] /index.html = anon /user/create = anon /user/** = authc /admin/** = authc, roles[administrator] /rest/** = authc, rest /remoting/rpc/** = authc, perms[ "remote:invoke" ] |
假如你有如下设置
/account/** = ssl, authc |
/account下的任何应用程序都将触动ssl和authc链
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架