身份认证,就是判断一个用户是否为合法用户的处理过程。最常用的简单身份认证方式就是通过核对用户输入的用户名和口令,看其与系统中存储的该用户的用户名和口令一致,来判断用户身份是否正确。
subject:主体
访问系统的用户,主体可以是用户、程序等,进行认证的都称为主体。
Principal:身份信息
主体(Subject)进行身份认证的标识,标识必须具有唯一性,如用户名、手机号、邮件地址等,一个主体可以有多个身份,但必须有一个主身份(Primary Principal)。
credential:凭证信息
只有主体自己知道的安全信息,比如密码、证书等
添加resource目录
org.apache.shiro
shiro-core
1.5.3
shiro配置文件以ini结尾,.ini复杂数据格式
创建配置文件shiro.ini
ini配置文件,用来给学习shiro书写相关权限数据,后期整合spring不用书写
#相当于配了三个用户
[users]
xiaochen=123
zhangsan=123456
lisi=789
package org.hz52;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.subject.Subject;
/**
* @Program: shiro_demo
* @Description:
* @Author: 52Hz
* @CreationTime: 2021年10月16日 13:12 星期六
**/
public class testAuthenticator {
public static void main(String[] args) {
//1.创建安全管理器
DefaultSecurityManager securityManager = new DefaultSecurityManager();
//2、给安全管理器设置realm:设置为ini里面的数据
securityManager.setRealm(new IniRealm("classpath:shiro.ini"));
//3、SecurityUtils 给全局安全工具类设置安全管理器
SecurityUtils.setSecurityManager(securityManager);
//4、关键对象 : subject主体
Subject subject = SecurityUtils.getSubject();
//5、创建令牌
UsernamePasswordToken token = new UsernamePasswordToken("xiaochen", "123");
try {
System.out.println("认证状态:" + subject.isAuthenticated());
subject.login(token);//用户认证
System.out.println("认证状态:" + subject.isAuthenticated());
} catch (UnknownAccountException e) {
e.printStackTrace();
System.out.println("认证失败:" + token.getUsername() + "用户名不存在");
} catch (IncorrectCredentialsException e) {
e.printStackTrace();
System.out.println("认证失败:" + token.getUsername() + "密码错误");
} catch (Exception e) {
e.printStackTrace();
}
}
}
查看实现类
上面的程序使用Shiro自带的IniRealm,Inirealm从配置文件中读取用户的信息,大部分情况下需要从系统的数据库中用户信息,所以需要自定义realm。
2、根据源码认证使用的是SimpleAcSimcountRealm
SimpleAcSimcountRealm的部分源码中有两个方法:一个是认证,一个是授权
package org.hz52.realm;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
/**
* @Program: shiro_demo
* @Description: 自定义Realm,将认证/授权数据来源转为数据库的实现
* @Author: 52Hz
* @CreationTime: 2021年10月16日 14:44 星期六
**/
public class CustmerRealm extends AuthorizingRealm {
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//在token中获取用户名
String principal = (String) token.getPrincipal();
System.out.println(principal);
//根据用户身份信息使用jdbc mybatis查询相关数据库
if ("xiaochen".equals(principal)) {
//SimpleAuthenticationInfo
// 参数1:数据库中的用户名
// 参数2:数据库中的密码
// 参数3:当前realm的名称this.getName()
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal, "123d", this.getName());
return simpleAuthenticationInfo;
}
return null;
}
}
无需ini文件
package org.hz52;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import org.hz52.realm.CustmerRealm;
/**
* @Program: shiro_demo
* @Description: 使用自定义Realm
* @Author: 52Hz
* @CreationTime: 2021年10月16日 14:48 星期六
**/
public class testCustmerAuthenticator {
public static void main(String[] args) {
//创建securityManager
DefaultSecurityManager securityManager = new DefaultSecurityManager();
//设置自定义Realm
securityManager.setRealm(new CustmerRealm());
//将安全工具类设置Realm
SecurityUtils.setSecurityManager(securityManager);
//通过安全工具类获取subject
Subject subject = SecurityUtils.getSubject();
//创建token
UsernamePasswordToken token = new UsernamePasswordToken("xiaochen", "123");
try {
subject.login(token);
} catch (UnknownAccountException e) {
e.printStackTrace();
System.out.println(token.getUsername() + "用户名错误");
} catch (IncorrectCredentialsException e) {
e.printStackTrace();
System.out.println(token.getUsername() + "密码错误");
}
}
}
实际应用是将盐和散列后的值存在数据库中,自动realm从数据库取出盐和加密后的值由shiro完成密码校验。
//创建一个md5算法
//当前没有进行加密
Md5Hash md5Hash = new Md5Hash();
//不设置散列次数则默认只做MD5
md5Hash.setBytes("123".getBytes());
System.out.println(md5Hash.toHex());
System.out.println(md5Hash.toBase64());
System.out.println(md5Hash.toString());
//使用md5
//使用构造方法才可以生成密钥
Md5Hash md5Hash=new Md5Hash("123");
System.out.println(md5Hash.toHex());
//使用md5+salt
Md5Hash md5Hash1=new Md5Hash("123","X0#31");
System.out.println(md5Hash1.toHex());
//使用md5+salt+hash散列(一般1024/2048)
Md5Hash md5Hash2 = new Md5Hash("123", "X0#31", 1024);
System.out.println(md5Hash2.toHex());
package org.hz52;
import org.apache.shiro.crypto.hash.Md5Hash;
/**
* @Program: shiro_demo
* @Description:
* @Author: 52Hz
* @CreationTime: 2021年10月16日 16:06 星期六
**/
public class testShiroMD5 {
public static void main(String[] args) {
//创建一个md5算法
//当前没有进行加密
// Md5Hash md5Hash = new Md5Hash();
// //不设置散列次数则默认只做MD5
// md5Hash.setBytes("123".getBytes());
// System.out.println(md5Hash.toHex());
// System.out.println(md5Hash.toBase64());
// System.out.println(md5Hash.toString());
//使用md5
//使用构造方法才可以生成密钥
Md5Hash md5Hash = new Md5Hash("123");
System.out.println(md5Hash.toHex());
//使用md5+salt
Md5Hash md5Hash1 = new Md5Hash("123", "X0#31");
System.out.println(md5Hash1.toHex());
//使用md5+salt+hash散列
Md5Hash md5Hash2 = new Md5Hash("123", "X0#31", 1024);
System.out.println(md5Hash2.toHex());
}
}
202cb962ac59075b964b07152d234b70
93018183dbbdc94a9fcf3166665bbaf5
6abca58de7461f2b5d795d3a6e79aaa6
数据库返回明文则制作equals
package org.hz52.realm;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
/**
* @Program: shiro_demo
* @Description: 使用自定义realm加入md5+salt+hash
* @Author: 52Hz
* @CreationTime: 2021年10月18日 9:25 星期一
**/
public class CustmerMD5Realm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//获取身份信息
String principal = (String) token.getPrincipal();
//根据用户名查询数据库
if ("xiaochen".equals(principal)) {
return new SimpleAuthenticationInfo(principal, "123", this.getName());
}
return null;
}
}
package org.hz52;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import org.hz52.realm.CustmerMD5Realm;
/**
* @Program: shiro_demo
* @Description:
* @Author: 52Hz
* @CreationTime: 2021年10月18日 9:27 星期一
**/
public class testCustmerMD5Authenticator {
public static void main(String[] args) {
//1、创建安全管理器
DefaultSecurityManager securityManager = new DefaultSecurityManager();
//2、注入realm
securityManager.setRealm(new CustmerMD5Realm());
//3、将安全管理器注入安全工具
SecurityUtils.setSecurityManager(securityManager);
//4、通过安全工具类获取subject
Subject subject = SecurityUtils.getSubject();
//5、认证
UsernamePasswordToken token = new UsernamePasswordToken("xiaochen", "123");
try {
subject.login(token);
System.out.println("登陆成功");
} catch (UnknownAccountException e) {
e.printStackTrace();
System.out.println("用户名错误");
} catch (IncorrectCredentialsException e) {
e.printStackTrace();
System.out.println("密码错误");
}
}
}
数据库返回md5,使用的时候需要切换验证
package org.hz52.realm;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
/**
* @Program: shiro_demo
* @Description: 使用自定义realm加入md5+salt+hash
* @Author: 52Hz
* @CreationTime: 2021年10月18日 9:25 星期一
**/
public class CustmerMD5Realm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//获取身份信息
String principal = (String) token.getPrincipal();
//根据用户名查询数据库
if ("xiaochen".equals(principal)) {
return new SimpleAuthenticationInfo(principal, "202cb962ac59075b964b07152d234b70", this.getName());
}
return null;
}
}
使用的时候需要切换验证
package org.hz52;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import org.hz52.realm.CustmerMD5Realm;
/**
* @Program: shiro_demo
* @Description:
* @Author: 52Hz
* @CreationTime: 2021年10月18日 9:27 星期一
**/
public class testCustmerMD5Authenticator {
public static void main(String[] args) {
//1、创建安全管理器
DefaultSecurityManager securityManager = new DefaultSecurityManager();
//2、注入realm
//设置realm使用hash凭证匹配器
CustmerMD5Realm realm = new CustmerMD5Realm();
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
credentialsMatcher.setHashAlgorithmName("md5");
realm.setCredentialsMatcher(credentialsMatcher);
securityManager.setRealm(realm);
//3、将安全管理器注入安全工具
SecurityUtils.setSecurityManager(securityManager);
//4、通过安全工具类获取subject
Subject subject = SecurityUtils.getSubject();
//5、认证
UsernamePasswordToken token = new UsernamePasswordToken("xiaochen", "123");
try {
subject.login(token);
System.out.println("登陆成功");
} catch (UnknownAccountException e) {
e.printStackTrace();
System.out.println("用户名错误");
} catch (IncorrectCredentialsException e) {
e.printStackTrace();
System.out.println("密码错误");
}
}
}
package org.hz52.realm;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
/**
* @Program: shiro_demo
* @Description: 使用自定义realm加入md5+salt+hash
* @Author: 52Hz
* @CreationTime: 2021年10月18日 9:25 星期一
**/
public class CustmerMD5Realm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//获取身份信息
String principal = (String) token.getPrincipal();
//根据用户名查询数据库
if ("xiaochen".equals(principal)) {
//参数1:数据库用户名 参数2:数据库MD5+Salt之后的密码 参数3:注册
return new SimpleAuthenticationInfo(principal,
"93018183dbbdc94a9fcf3166665bbaf5",
ByteSource.Util.bytes("X0#31"),
this.getName());
}
return null;
}
}
package org.hz52;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import org.hz52.realm.CustmerMD5Realm;
/**
* @Program: shiro_demo
* @Description:
* @Author: 52Hz
* @CreationTime: 2021年10月18日 9:27 星期一
**/
public class testCustmerMD5Authenticator {
public static void main(String[] args) {
//1、创建安全管理器
DefaultSecurityManager securityManager = new DefaultSecurityManager();
//2、注入realm
//设置realm使用hash凭证匹配器
CustmerMD5Realm realm = new CustmerMD5Realm();
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
credentialsMatcher.setHashAlgorithmName("md5");
realm.setCredentialsMatcher(credentialsMatcher);
securityManager.setRealm(realm);
//3、将安全管理器注入安全工具
SecurityUtils.setSecurityManager(securityManager);
//4、通过安全工具类获取subject
Subject subject = SecurityUtils.getSubject();
//5、认证
UsernamePasswordToken token = new UsernamePasswordToken("xiaochen", "123");
try {
subject.login(token);
System.out.println("登陆成功");
} catch (UnknownAccountException e) {
e.printStackTrace();
System.out.println("用户名错误");
} catch (IncorrectCredentialsException e) {
e.printStackTrace();
System.out.println("密码错误");
}
}
}
package org.hz52.realm;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
/**
* @Program: shiro_demo
* @Description: 使用自定义realm加入md5+salt+hash
* @Author: 52Hz
* @CreationTime: 2021年10月18日 9:25 星期一
**/
public class CustmerMD5Realm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//获取身份信息
String principal = (String) token.getPrincipal();
//根据用户名查询数据库
if ("xiaochen".equals(principal)) {
//参数1:数据库用户名 参数2:数据库MD5+Salt之后的密码 参数3:注册
return new SimpleAuthenticationInfo(principal,
"6abca58de7461f2b5d795d3a6e79aaa6",
ByteSource.Util.bytes("X0#31"),
this.getName());
}
return null;
}
}
package org.hz52;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import org.hz52.realm.CustmerMD5Realm;
/**
* @Program: shiro_demo
* @Description:
* @Author: 52Hz
* @CreationTime: 2021年10月18日 9:27 星期一
**/
public class testCustmerMD5Authenticator {
public static void main(String[] args) {
//1、创建安全管理器
DefaultSecurityManager securityManager = new DefaultSecurityManager();
//2、注入realm
//设置realm使用hash凭证匹配器
CustmerMD5Realm realm = new CustmerMD5Realm();
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
//设置加密算法
credentialsMatcher.setHashAlgorithmName("md5");
//设置散列次数
credentialsMatcher.setHashIterations(1024);
realm.setCredentialsMatcher(credentialsMatcher);
securityManager.setRealm(realm);
//3、将安全管理器注入安全工具
SecurityUtils.setSecurityManager(securityManager);
//4、通过安全工具类获取subject
Subject subject = SecurityUtils.getSubject();
//5、认证
UsernamePasswordToken token = new UsernamePasswordToken("xiaochen", "123");
try {
subject.login(token);
System.out.println("登陆成功");
} catch (UnknownAccountException e) {
e.printStackTrace();
System.out.println("用户名错误");
} catch (IncorrectCredentialsException e) {
e.printStackTrace();
System.out.println("密码错误");
}
}
}