【Shiro】SimpleAuthenticationInfo如何验证password

一、前言

通篇的关键就是知道ShiroRealm类重写的doGetAuthenticationInfo这个方法,到底是谁的方法。
在这里插入图片描述
从上图我们可以知道,ShiroRealm最终继承到了AuthenticatingRealm这个方法。

二、自定义的ShiroRealm类

ps:该图中①上的注释是没看过底层的时候,先入为主的理解。
在这里插入图片描述

在自定义的ShiroRealm中,看上去像验证的就是①,但也只是创建了一个SimpleAuthenticationInfo对象,最后②return出去就没了。
小白的我尝试Debug去找实际执行的代码,却只跳到了SimpleAuthenticationInfo类中,最后一无所获。

我们回过头看下ShiroRealm,它继承了AuthorizingRealm
在这里插入图片描述
进到了AuthorizingRealm里面,你会发现还是什么没有,但你会注意到,它继承了AuthenticatingRealm(他们的关系如 一前言 所示)。

三、AuthenticatingRealm类

在该类中,通过Find可以发现,AuthenticatingRealm类中含有抽象方法doGetAuthenticationInfo,也就意味着,ShiroRealm中@Override就是它。
在这里插入图片描述
我们在看下是谁调用了这个方法,最后可以发现,在AuthenticatingRealm类中,getAuthenticationInfo()方法里的②调用了该方法;也就是说,我们在ShiroRealm中return的内容在这里。
在这里插入图片描述

讲到这里,我们分别在看下①和③。

1、getCachedAuthenticationInfo(token)方法

①从字面意思,参数和最后对象的类名,可以知道,这就是获取token中的用户名和密码。

  • 补充:看到这里眼睛尖的朋友会发现,在上图中,①和②都是返回info(AuthenticationInfo类);代码逻辑是:
// 通过缓存和token获取用户信息
info = getCachedAuthenticationInfo(token);
// 用户信息不存在
if(info == null{
	// 在ShiroRealm中@Override,获取登录用户的信息
	info = doGetAuthenticationInfo(token);
	...
}

AuthenticationInfo类(如下图)和AuthenticationToken有点类似,可以扩展看下shiro AuthenticationToken体系
在这里插入图片描述

getCachedAuthenticationInfo主要是看缓存和token,获取用户信息。
在这里插入图片描述

2、assertCredentialsMatch(token, info)方法

在这里插入图片描述
在该方法里面有CredentialsMatcher(),虽然我不知道是什么,但下面的if里面调用了该对象的方法cm.doCredentialsMatch(token, info)
在这里插入图片描述
从接口上可以看到有4个实现类,废话不多说,一个个看了后发现第一个只返回true,第二个处理有salt的,第四个处理没salt的,第三个太长了没细看。

对比下来,salt应该就是我们要找的。
在这里插入图片描述

ps:加密对小白的我难度有点大,暂时就不再深究了,有兴趣的大佬们可以去看看。

可以看到这里,我们就知道doCredentialsMatch方法中,最后token解密的数据和数据库中的数据相同,就会返回true,也就意味着验证通过。

如果返回false,就会抛出IncorrectCredentialsException(看assertCredentialsMatch(token, info)方法的第一张图),在controller中就会捕获该异常,返回给前端。
在这里插入图片描述

四、总结图

在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Shiro 是一个强大的 Java 安全框架,提供了身份认证、授权、加密等功能。以下是一个简单的 Shiro 权限验证代码示例: 1. 配置 Shiro 安全管理器 ```java // 创建一个 DefaultSecurityManager 对象 DefaultSecurityManager securityManager = new DefaultSecurityManager(); // 设置 Realm securityManager.setRealm(myRealm); // 将 SecurityManager 设置为全局的安全管理器 SecurityUtils.setSecurityManager(securityManager); ``` 2. 创建一个自定义 Realm 类 ```java public class MyRealm extends AuthorizingRealm { // 授权方法 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // 获取当前用户 String username = (String) principals.getPrimaryPrincipal(); // 根据用户名查询该用户的角色和权限 Set<String> roles = userService.findRolesByUsername(username); Set<String> permissions = userService.findPermissionsByUsername(username); // 创建 SimpleAuthorizationInfo 对象,并设置角色和权限 SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); authorizationInfo.setRoles(roles); authorizationInfo.setStringPermissions(permissions); return authorizationInfo; } // 认证方法 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { // 获取用户名和密码 String username = (String) token.getPrincipal(); String password = new String((char[]) token.getCredentials()); // 查询用户是否存在 User user = userService.findByUsername(username); if (user == null) { throw new UnknownAccountException("用户不存在"); } // 验证密码 if (!passwordEncoder.matches(password, user.getPassword())) { throw new IncorrectCredentialsException("密码错误"); } // 创建 SimpleAuthenticationInfo 对象,并设置用户名和密码 SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username, password, getName()); return authenticationInfo; } } ``` 3. 在 Controller 中进行权限验证 ```java @Controller public class UserController { @RequiresPermissions("user:list") @GetMapping("/user/list") public String list() { // 用户列表页面 return "user/list"; } @RequiresPermissions("user:add") @GetMapping("/user/add") public String add() { // 添加用户页面 return "user/add"; } @RequiresPermissions("user:edit") @GetMapping("/user/edit") public String edit() { // 编辑用户页面 return "user/edit"; } } ``` 在上述代码中,@RequiresPermissions 注解表示该方法需要进行权限验证。如果当前用户拥有对应的权限,则可以访问该方法;否则将抛出 UnauthorizedException 异常。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值