二、Shiro 认证开发
I、java开发
环境准备
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.2</version>
</dependency>
</dependencies>
shiro配置文件: shiro.ini
[users]
zhang3=123123
li4=123456
测试
//测试认证
public class TestAuthor {
/**
* 认证
* 安全管理器
* 获取主题
* token
*
*/
public static void main(String[] args) {
//通过安全管理器工厂
IniSecurityManagerFactory iniSecurityManagerFactory = new IniSecurityManagerFactory("classpath:shiro.ini");
//获得安全管理器工厂
SecurityManager securityManager = iniSecurityManagerFactory.getInstance();
//将安全管理器交给安全工具类
SecurityUtils.setSecurityManager(securityManager);
//主体对象
Subject subject = SecurityUtils.getSubject();
//构建token
UsernamePasswordToken token = new UsernamePasswordToken("zhang3", "123123");
try {
subject.login(token);
} catch (AuthenticationException e) {
e.printStackTrace();
}
//验证是否通过
System.out.println(subject.isAuthenticated());
}
}
异常
IncorrectCredentialsException:密码输入错误
UnknownAccountException:账户对比失败
DisabledAccountException:帐号被禁用
LockedAccountException:帐号被锁定
ExcessiveAttemptsException:登录失败次数过多
ExpiredCredentialsException:凭证过期
底层认证思路

public class MyRealm extends AuthenticatingRealm{
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
/**
* 假装查询数据库
*
*
*/
//获取用户名
String principal = (String) authenticationToken.getPrincipal();
if (principal.equals("zhang3")){
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo("zhang3", "123123", this.getName());
return simpleAuthenticationInfo;
}
return null;
}
}
II、Shiro认证过程
①. 应用程序代码调用 Subject.login 方法,传递创建好的包含终端用户的 Principals(身份)和 Credentials(凭证)的 AuthenticationToken 实例
②. Subject 实例: 通常为 DelegatingSubject(或子类)委托应用程序的 SecurityManager 通过调用securityManager.login(token) 开始真正的验证。
③. SubjectManager 接收 token,调用内部的 Authenticator 实例调用 authenticator.authenticate(token).Authenticator 通常是一个 ModularRealmAuthenticator 实例, 支持在身份验证中协调一个或多个Realm 实例
④. 如果应用程序中配置了一个以上的 Realm, ModularRealmAuthenticator 实例将利用配置好的AuthenticationStrategy 来启动 Multi-Realm 认证尝试. 在Realms 被身份验证调用之前, 期间和以后,AuthenticationStrategy 被调用使其能够对每个Realm 的结果作出反应.
⑤. 每个配置的 Realm 用来帮助看它是否支持提交的 AuthenticationToken. 如果支持, 那么支持 Realm 的 getAuthenticationInfo 方法将会伴随着提交的 token 被调用. getAuthenticationInfo 方法有效地代表一个特定 Realm 的单一的身份验证尝试
III、Shiro的加密认证
测试加密的结果,元数据为12313,盐为1345,散列1024次=b8cc2120cdf1554cf35603e08f7f5524
public class TestMD5Hash {
public static void main(String[] args) {
//param 元数据 盐 散列
Md5Hash md5Hash = new Md5Hash("123123","1345",1024);
String s = md5Hash.toHex();
System.out.println(s);
}
}
自定义规则
public class MyRealm2 extends AuthenticatingRealm {
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String principal = (String) authenticationToken.getPrincipal();
if (principal.equals("zhang3")){
return new SimpleAuthenticationInfo("zhang3","b8cc2120cdf1554cf35603e08f7f5524", ByteSource.Util.bytes("1345"),this.getName());
}
return null;
}
}
配置文件定义规则和加密规则
[main]
# 声明凭证匹配器
credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
# 声明realm
realm2=com.baizhi.shiro2.MyRealm2
securityManager.realms=$realm2
# 告知realm使用HashedCredentialsMatcher 为凭证匹配器
realm2.credentialsMatcher=$credentialsMatcher
# 告知安全管理器使用自定义
securityManager.realms=$realm2
# 告知Shiro算法的名称
credentialsMatcher.hashAlgorithmName=md5
credentialsMatcher.hashIterations=1024
public class TestAuthen2 {
public static void main(String[] args) {
IniSecurityManagerFactory securityManagerFactory = new IniSecurityManagerFactory("classpath:shiro1.ini");
SecurityManager securityManager = securityManagerFactory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("zhang3", "123123");
try {
subject.login(token);
} catch (UnknownAccountException e) {
System.out.println("用户名错误");
} catch (IncorrectCredentialsException e){
System.out.println("密码错误");
}
boolean authenticated = subject.isAuthenticated();
System.out.println(authenticated);
}
}

浙公网安备 33010602011771号