代码
1.先不用数据库来进行身份认证,--我们ini文件,window系统文件,该文件中可以存放账号和密码。
(1) 创建一个maven java工程
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.9.0</version>
</dependency>
(2)创建ini文件
(3)测试代码
public class TestShiro01 {
public static void main(String[] args) {
//1.获取SecutiryManager对象
DefaultSecurityManager securityManager = new DefaultSecurityManager();
//2.读取ini文件
IniRealm iniRealm = new IniRealm("classpath:shiro.ini");
//3.设置securityManager的realm
securityManager.setRealm(iniRealm);
//4. 设置securityManager上下文生效
SecurityUtils.setSecurityManager(securityManager);
//5. 获取subject主体对象
Subject subject= SecurityUtils.getSubject();
try {
//UsernamePasswordToken作用就是封装你输入的账号和密码 是客户输入的账号和密码
UsernamePasswordToken token=new UsernamePasswordToken("zhangsan","123456");
//抛出异常 比对shiro中realm把你自带对比
subject.login(token);
System.out.println("登录成功");
}catch (Exception e){
e.printStackTrace();
System.out.println("账号或密码错误");
}
}
}
认证的原理
Subject: 主题 登录信息提交给SecurityManager, --->认证器Authenticator---->根据你的realm提供的数据进行相关的认证。 realm---与数据源交互的类。
授权
修改ini文件
修改代码
public class TestShiro01 {
public static void main(String[] args) {
//1.获取SecutiryManager对象
DefaultSecurityManager securityManager = new DefaultSecurityManager();
// //2.读取ini文件
IniRealm iniRealm = new IniRealm("classpath:shiro.ini");
//3.设置securityManager的realm
securityManager.setRealm(iniRealm);
//4. 设置securityManager上下文生效
SecurityUtils.setSecurityManager(securityManager);
//5. 获取subject主体对象
Subject subject= SecurityUtils.getSubject();
try {
//UsernamePasswordToken作用就是封装你输入的账号和密码 是客户输入的账号和密码
UsernamePasswordToken token=new UsernamePasswordToken("zhangsan","123456");
//抛出异常 比对shiro中realm把你自带对比
subject.login(token);
System.out.println("登录成功");
}catch (Exception e){
e.printStackTrace();
System.out.println("账号或密码错误");
}
// subject.logout();
System.out.println("====================================================登录后=====================================");
boolean authenticated = subject.isAuthenticated();
if(authenticated){
//判断当前登录者是否具有user:query权限
boolean permitted = subject.isPermitted("user:update");
System.out.println(permitted);
//从角色角度
boolean b = subject.hasRole("role1");
System.out.println(b);
}else{
System.out.println("请先认证");
}
}
}
认证的底层源码。
我们分析源码 我们的最终认证交于realm完成认证功能,返回一个info, 如果info不为null,则进行密码比对。如果我们希望用数据库中的账号和密码完成认证功能,则只需要我们自定义一个类并继承AuthenticatingRealm。
自定义Realm 认证
public class MyRealm extends AuthenticatingRealm {
private UserService userService=new UserService();
//该方法用于完成认证的功能
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//1.根据token获取账号
String username = (String) authenticationToken.getPrincipal();
//2.根据账号查询用户信息
User user = userService.findByUsername(username);
if(user!=null){
//从数据库中获取的密码
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
return info;
}
return null;
}
}
加密
shiro它提供了很多中加密器。其他使用最多就是HashedCredentialsMatcher。它的底层使用的还是Md5加密。了解一下MD5加密
public class Test03 {
public static void main(String[] args) {
//source:需要加密的明文
Md5Hash md5Hash = new Md5Hash("123456");
System.out.println(md5Hash);//e10adc3949ba59abbe56e057f20f883e密文---默认md5加密是不可逆的。但是网上由一些破解软件
//salt:盐
Md5Hash md5Hash1=new Md5Hash("123456","abc?!");
System.out.println(md5Hash1);
//设置n次加密
Md5Hash md5Hash2 = new Md5Hash("123456","abc?!",1024);
}
}
shiro使用密码加密器
修改realm代码
自定义realm的授权功能
public class MyRealm extends AuthorizingRealm {
private UserService userService = new UserService();
//什么时候执行该方法: 当你进行权限校验时会执行该方法
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
User user = (User) principalCollection.getPrimaryPrincipal();
//根据账号查询该用户具有哪些权限
List<String> list= userService.findPermissionByUsername(user.getUsername());
if(list!=null&&list.size()>0){
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
info.addStringPermissions(list);
return info;
}
return null;
}
//
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//1.根据token获取账号
String username = (String) authenticationToken.getPrincipal();
//2.根据账号查询用户信息
User user = userService.findByUsername(username);
if(user!=null){
//从数据库中获取的密码
ByteSource credentialsSalt=ByteSource.Util.bytes(user.getSalt());
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),credentialsSalt,this.getName());
return info;
}
return null;
}
}
测试:
public class TestShiro04 {
public static void main(String[] args) {
DefaultSecurityManager securityManager=new DefaultSecurityManager();
MyRealm myRealm=new MyRealm();
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
credentialsMatcher.setHashAlgorithmName("MD5");
credentialsMatcher.setHashIterations(1024);
myRealm.setCredentialsMatcher(credentialsMatcher);
securityManager.setRealm(myRealm);
SecurityUtils.setSecurityManager(securityManager);
Subject subject = SecurityUtils.getSubject();
try {
UsernamePasswordToken token = new UsernamePasswordToken("ykq", "123456");
subject.login(token);
System.out.println(subject.isPermitted("user:query"));
System.out.println(subject.isPermitted("user:update"));
}catch (Exception e){
System.out.println("账号密码错误");
}
}
}