Shiro 简单的认证
需要导入的依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
</dependency>
<!-- shiro-core 依赖于这个依赖 -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1</version>
</dependency>
1,基本的认证(用配置文件模拟数据库获取 用户信息)
1.1,创建安全管理器
//创建安全管理器
IniSecurityManagerFactory iniSecurityManagerFactory = new IniSecurityManagerFactory("classpath:shiro/shiroTest1.ini");
SecurityManager securityManager = iniSecurityManagerFactory.getInstance();
new IniSecurityManagerFactory("classpath:shiro/shiroTest1.ini"); .ini是shiro的配置文件类型,里面的是用户的信息
shiroTest1.ini 配置文件内容
[users]
lisi=123456
zhangsan=123456
1.2,告诉安全工具类,使用哪一个安全管理器
SecurityUtils.setSecurityManager(securityManager);
1.3,获取主体
Subject subject = SecurityUtils.getSubject();
1.4,认证主体携带数据
AuthenticationToken token = new UsernamePasswordToken("zhangsan", "123456");
1.5,认证状态
//boolean 类型 true 认证成功 false认证失败
boolean flag = subject.isAuthenticated();
1.6,简单的测试代码
public class TestShiro1 {
public static void main(String[] args) {//测试1 简单的认证
//创建安全管理器
IniSecurityManagerFactory iniSecurityManagerFactory = new IniSecurityManagerFactory("classpath:shiro/shiroTest1.ini");
SecurityManager securityManager = iniSecurityManagerFactory.getInstance();
//告诉安全工具类,使用哪一个安全管理器
SecurityUtils.setSecurityManager(securityManager);
//获取主体
Subject subject = SecurityUtils.getSubject();
//认证状态
boolean flag = subject.isAuthenticated();
System.out.println("认证状态: "+flag);
//认证主体携带数据
AuthenticationToken token = new UsernamePasswordToken("zhangsan", "123456");
try {
subject.login(token);
System.out.println("当前认证成功!");
}catch (UnknownAccountException e) {
// TODO: handle exception
System.out.println("账户错误!");
}catch (IncorrectCredentialsException e) {
// TODO: handle exception
System.out.println("密码错误!");
}
flag = subject.isAuthenticated();
System.out.println("认证状态: "+flag);
}
}
2,从数据库获取,用户信息认证
2.1,需要自定义realm,创建类并继承AuthenticatingRealm,复写doGetAuthenticationInfo方法
public class MyRealm extends AuthenticatingRealm{
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authentionToken) throws AuthenticationException {
// TODO Auto-generated method stub
return null;
}
}
2.2,获取用户名
String principal = (String)authentionToken.getPrincipal();
2.3,调用 dao层获取用户信息进行对比账号和密码,我这里没有调用dao层 直接模拟的,this.getName 是用来realm的唯一名称
//调用dao 根据用户名 查询用户对象
//这个应该直接从数据库调用 然后在进行 new SimpleAuthenticationInfo("zhangsan","123456",this.getName());
//然后进行比对
if(principal.equals("zhangsan")) {
//zhangsan 123456 应该是 从数据库 中 查询出来的 this.getName 是用来realm的唯一名称
return new SimpleAuthenticationInfo("zhangsan","123456",this.getName());
//然后凭证匹配器进行比对 不用自己进行比对了
}
2.4,自定义MyRealm的简单代码
/**
* 用来调用dao层 查询 用户数据然后进行认证
* @author wangmx
*/
public class MyRealm extends AuthenticatingRealm{
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authentionToken) throws AuthenticationException {
// TODO Auto-generated method stub
//获取用户名
String principal = (String)authentionToken.getPrincipal();
System.out.println("获取的用户名:"+principal);
//调用dao 根据用户名 查询用户对象
//这个应该直接从数据库调用 然后在进行 new SimpleAuthenticationInfo("zhangsan","123456",this.getName());
//然后进行比对
if(principal.equals("zhangsan")) {
//zhangsan 123456 应该是 从数据库 中 查询出来的 this.getName 是用来realm的唯一名称
return new SimpleAuthenticationInfo("zhangsan","123456",this.getName());
//然后凭证匹配器进行比对 不用自己进行比对了
}
return null;
}
}
2.5,shiro.ini配置文件的配置 主要 的作用是让他走自定义的安全管理器(Realm)
#自定义realm的配置 不让他走 自己内部的realm 走我自定意的realm
[main]
myRealm=com.wangmx.shiroTest.MyRealm
#让安全管理器 走自定义的realm
securityManager.realms=$myRealm
2.6,认证的代码 只需要替换 new IniSecurityManagerFactory("classpath:shiro/shiro.ini"); 的配置文件,其他不变
IniSecurityManagerFactory iniSecurityManagerFactory = new IniSecurityManagerFactory("classpath:shiro/shiro.ini");
SecurityManager securityManager = iniSecurityManagerFactory.getInstance();
3,MD5认证
3.1,shiro有自己的MD5的方法 new Md5Hash("123456","ABCD",1024); ,new Md5Hash("123456","ABCD");,new Md5Hash("123456","ABCD"); 第一个 是 加盐加散列,第二个是加盐,第三个什么都不加
//原始数据 盐值 散列
Md5Hash md5Hash = new Md5Hash("123456","ABCD",1024);
String s = md5Hash.toHex();
3.2,Md5Realm 继承 AuthenticatingRealm 并且复写 doGetAuthenticationInfo 方法和基本的基本上差不多 只是 new SimpleAuthenticationInfo() 参数有所不同
public class Md5Realm extends AuthenticatingRealm{
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// TODO Auto-generated method stub
return null;
}
}
返回的写法,ByteSource.Util.bytes("ABCD") 是加盐
new SimpleAuthenticationInfo(username,password,ByteSource.Util.bytes("ABCD"),this.getName());
自定义Realm的全部代码
public class Md5Realm extends AuthenticatingRealm{
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// TODO Auto-generated method stub
String principal = (String)authenticationToken.getPrincipal();
if(principal.equals("zhangsan")) {
String username="zhangsan";
String password = "3d53b73c485f523ef2fe45f2b8dd3c58";
return new SimpleAuthenticationInfo(username,password,ByteSource.Util.bytes("ABCD"),this.getName());
}
return null;
}
}
3.3,shiro_Md5.ini 的配置 基本上是告诉shiro 加密的类型和散列的次数,和修改凭证匹配器
[main]
#声明凭证匹配器
hashedCredentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
hashedCredentialsMatcher.hashAlgorithmName=md5
hashedCredentialsMatcher.hashIterations=1024
#声明realm
myRealm=com.wangmx.shiroMd5Test.Md5Realm
#告知realm使用声明的凭证匹配器
myRealm.credentialsMatcher=$hashedCredentialsMatcher
#让安全管理器 走自定义的realm
securityManager.realms=$myRealm
3.4,认证的代码和基本认证一样就是替换shiro_Md5.ini,new IniSecurityManagerFactory("classpath:shiro/shiro_Md5.ini");
IniSecurityManagerFactory iniSecurityManagerFactory = new IniSecurityManagerFactory("classpath:shiro/shiro_Md5.ini");
SecurityManager securityManager = iniSecurityManagerFactory.getInstance();
简单的测试代码 可充当Controller
public class TestShiroAuthen1 {
public static void main(String[] args) {
IniSecurityManagerFactory iniSecurityManagerFactory = new IniSecurityManagerFactory("classpath:shiro/shiro_Md5.ini");
SecurityManager securityManager = iniSecurityManagerFactory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
Subject subject = SecurityUtils.getSubject();
AuthenticationToken token = new UsernamePasswordToken("zhangsan", "123456");
try {
subject.login(token);
System.out.println("认证成功!");
}catch (UnknownAccountException e) {
// TODO: handle exception
System.out.println("账户错误!");
}catch (IncorrectCredentialsException e) {
// TODO: handle exception
System.out.println("密码错误!");
}
System.out.println("认证状态:"+subject.isAuthenticated());
}
}