Shiro笔记身份验证
Posted Shadowplay
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Shiro笔记身份验证相关的知识,希望对你有一定的参考价值。
Shiro笔记(二)身份验证
一、核心代码
1 @Test 2 public void helloWorldTest(){ 3 IniSecurityManagerFactory factory = 4 new IniSecurityManagerFactory("classpath:shiro-jdbc-realm.ini"); 5 SecurityManager manager = factory.getInstance(); 6 //全局设置,一次即可 7 SecurityUtils.setSecurityManager(manager); 8 Subject subject = SecurityUtils.getSubject(); 9 UsernamePasswordToken token = 10 new UsernamePasswordToken("Peter", "123"); 11 try{ 12 subject.login(token); 13 }catch (AuthenticationException e){ 14 e.printStackTrace(); 15 } 16 17 Assert.assertEquals(true,subject.isAuthenticated()); 18 //退出登录 19 subject.logout();
shiro.ini文件:
[users] Peter=123 Tom=321
二、身份认证流程:
Authenticator 可能会委托给相应的 AuthenticationStrategy 进行多 Realm 身份验证,默认
ModularRealmAuthenticator 会调用 AuthenticationStrategy 进行多 Realm 身份验证;
Authenticator 会把相应的 token 传入 Realm,从 Realm 获取身份验证信息
三、Realm
Shiro 从从 Realm 获取安全数据(如用户、角色、权限)
Reaml接口:
1 public interface Realm { 2 //获得唯一的名字 3 String getName(); 4 //判断此realm是否支持此token 5 boolean supports(AuthenticationToken token); 6 //获取token认证信息 7 AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException; 8 }
一)单Realm配置
1 public class MyRealm implements Realm{ 2 3 public String getName() { 4 return "myRealm"; 5 } 6 7 public boolean supports(AuthenticationToken authenticationToken) { 8 //仅支持UsernamePasswordToken类型 9 return authenticationToken instanceof UsernamePasswordToken; 10 } 11 12 public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { 13 //获取用户名 14 String username= (String) token.getPrincipal(); 15 //获取密码 16 String password=new String((char[]) token.getCredentials()); 17 if(!"Peter".equals(username)){ 18 throw new UnknownAccountException(); 19 } 20 if(!"123".equals(password)){ 21 throw new IncorrectCredentialsException(); 22 } 23 return new SimpleAuthenticationInfo(username,password,getName()); 24 } 25 }
ini文件指定:
1 myRealm=com.tang.shirotest.LoginLogoutTest 2 securityManager.realms=$myRealm
二)JDBC Realm的使用
1 [main] 2 jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm 3 dataSource=com.alibaba.druid.pool.DruidDataSource 4 dataSource.driverClassName=com.mysql.jdbc.Driver 5 dataSource.url=jdbc:mysql://localhost:3306/shiro 6 dataSource.username=root 7 dataSource.password=jiapi1990 8 jdbcRealm.dataSource=$dataSource 9 securityManager.realms=$jdbcRealm
三)Authenticator及AuthenticationStrategy
Authenticator的职责是验证用户账号,接口为:
public interface Authenticator { AuthenticationInfo authenticate(AuthenticationToken var1) throws AuthenticationException; }
SecurityManager 接口继承了 Authenticator,另外还有一个 ModularRealmAuthenticator 实现,
其委托给多个 Realm 进行验证,验证规则通过 AuthenticationStrategy 接口指定,默认提供
的实现:
FirstSuccessfulStrategy:只要有一个 Realm 验证成功即可,只返回第一个 Realm 身份验证
成功的认证信息,其他的忽略;
AtLeastOneSuccessfulStrategy:只要有一个 Realm 验证成功即可,和 FirstSuccessfulStrategy
不同,返回所有 Realm 身份验证成功的认证信息;
AllSuccessfulStrategy:所有 Realm 验证成功才算成功,且返回所有 Realm 身份验证成功的
认证信息,如果有一个失败就失败了
ModularRealmAuthenticator 默认使用 AtLeastOneSuccessfulStrategy 策略。
ini文件:
1 #指定 securityManager 的 authenticator 实现 2 authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator 3 securityManager.authenticator=$authenticator 4 #指定 securityManager.authenticator 的 authenticationStrategy 5 allSuccessfulStrategy=org.apache.shiro.authc.pam.AllSuccessfulStrategy 6 securityManager.authenticator.authenticationStrategy=$allSuccessfulStrategy 7 myRealm1=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm1 8 myRealm2=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm2 9 myRealm3=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm3 10 securityManager.realms=$myRealm1,$myRealm3
AuthenticationStrategy接口:
1 public interface AuthenticationStrategy { 2 //在所有 Realm 验证之前调用 3 AuthenticationInfo beforeAllAttempts(Collection<? extends Realm> realms, AuthenticationToken token) throws AuthenticationException; 4 //在每个 Realm 之前调用 5 AuthenticationInfo beforeAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException; 6 //在每个 Realm 之后调用 7 AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo singleRealmInfo, AuthenticationInfo aggregateInfo, Throwable t) 8 throws AuthenticationException; 9 ////在所有 Realm 之后调用 10 AuthenticationInfo afterAllAttempts(AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException; 11 }
自定义实现:
1 public class AtLeastTwoAuthenticatorStrategy extends AbstractAuthenticationStrategy { 2 3 @Override 4 public AuthenticationInfo beforeAllAttempts(Collection<? extends Realm> realms, AuthenticationToken token) throws AuthenticationException { 5 return new SimpleAuthenticationInfo();//返回一个权限的认证信息 6 } 7 8 @Override 9 public AuthenticationInfo beforeAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException { 10 return aggregate;//返回之前合并的 11 } 12 13 @Override 14 public AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo singleRealmInfo, AuthenticationInfo aggregateInfo, Throwable t) throws AuthenticationException { 15 AuthenticationInfo info; 16 if (singleRealmInfo == null) { 17 info = aggregateInfo; 18 } else { 19 if (aggregateInfo == null) { 20 info = singleRealmInfo; 21 } else { 22 info = merge(singleRealmInfo, aggregateInfo); 23 } 24 } 25 26 return info; 27 } 28 29 @Override 30 public AuthenticationInfo afterAllAttempts(AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException { 31 if (aggregate == null || CollectionUtils.isEmpty(aggregate.getPrincipals()) || aggregate.getPrincipals().getRealmNames().size() < 2) { 32 throw new AuthenticationException("Authentication token of type [" + token.getClass() + "] " + 33 "could not be authenticated by any configured realms. Please ensure that at least two realm can " + 34 "authenticate these tokens."); 35 } 36 37 return aggregate; 38 } 39 }
以上是关于Shiro笔记身份验证的主要内容,如果未能解决你的问题,请参考以下文章