当前位置: 首页 > 工具软件 > shiro-redis > 使用案例 >

shiro使用爬坑记录之shiro-redis

沃弘图
2023-12-01

shiro使用爬坑记录之shiro-redis

前言

​ 权限认证使用的一直都是shiro,因为项目重构导致之前的认证不可用,故本片文章记录排错过程。

环境

  • SpringBoot 2.1.3.RELEASE
  • Mybatis-plus 3.1.2
  • Shiro 1.4.0
  • Jwt 3.7.0
  • shiro-redis 3.1.0

错误信息

class java.lang.String must has getter for field: authCacheKey or id We need a field to identify this Cache Object in Redis. So you need to defined an id field which you can get unique id to identify this principal. For example, if you use UserInfo as Principal class, the id field maybe userId, userName, email, etc. For example, getUserId(), getUserName(), getEmail(), etc. Default value is authCacheKey or id, that means your principal object has a method called "getAuthCacheKey()" or "getId()"

根据以上错误信息即官网使用介绍,是进行doGetAuthenticationInfo认证时返回的SimpleAuthenticationInfo中没有id或者getAuthCacheKey

问题排查

通过shiro-redis使用文档介绍,需要增加以下配置来支持自定义id

...
public RedisCacheManager cacheManager() {
    RedisCacheManager redisCacheManager = new RedisCacheManager();
    redisCacheManager.setRedisManager(redisManager());
    redisCacheManager.setPrincipalIdFieldName("id");//需要和SimpleAuthenticationInfo对象中的属性id一致
    return redisCacheManager;
}
...
@Override
public AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
  	UserInfo user = authentUser.getUserByToken(token);//获取登陆用户,用户中必须包含id属性
    return new SimpleAuthenticationInfo(user,token, user.getName());
}

但是实际情况是,这些配置我们都有,且重构后的代码可以正常使用,经过反复排查发现重构后的用户对象改用了继承的方式,即:

public class UserInfo{...}
public class extends LoginUser{...}

授权信息:

...
@Override
public AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
  	LoginUser user = authentUser.getUserByToken(token);//继承了UserInfo
    return new SimpleAuthenticationInfo(user,token, user.getName());
}

最终使用的是LoginUser对象进行的登陆,而恰好shiro-redis 不持支使用继承方式获取父类的id,故问题根源找到了。

解决方案

既然问题找见了,那么就很好解决了

重写父类id属性

在子类中重写父类的id,即:

public class extends LoginUser{
    private Integer id;
    getter...
    setter...
}

返回授权信息:

...
@Override
public AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
  	LoginUser user = authentUser.getUserByToken(token);//此处的LoginUser已覆盖了父类id
    return new SimpleAuthenticationInfo(user,token, user.getName());
}
移除子类,直接使用父类

直接弃用子类,登陆信息直接使用父类,即:

...
@Override
public AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
  	UserInfo user = authentUser.getUserByToken(token);//此处的LoginUser已覆盖了父类id
    return new SimpleAuthenticationInfo(user,token, user.getName());
}

总结

以上就是本次解决问题的全部内容,真是马虎不得。

如果这篇博客对你有帮助的话,记得给我点个赞,你的鼓励是对我最大的支持!

 类似资料: