Redis反序列化的一次问题

redis反序列化的一次问题

1. 问题描述

springboot+redis不少用,但是一直没遇到什么问题,直接代码拷贝上去就用了。这次结合spring-security,将自定义的spring-security的UserDetails接口的实现类SecurityUser,反序列化取出时报错。

b 复制代码
org.springframework.data.redis.serializer.SerializationException: Could not read JSON: Cannot construct instance of `com.jankin.inoteadmin.security.entity.SecurityUser` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
	......
org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer.deserialize(GenericJackson2JsonRedisSerializer.java:165)

2. 问题解读

我猜肯定有人骂我了,上面问题描述不是很清晰了吗 no Creators, like default constructor, exist 。我的回答是,该骂,大骂特骂~

作为一名不称职的代码搬砖工,我遇到问题时,第一是间是查看是否实现了Serializable接口。确认父接口UserDetails实现了该接口还不死心,然后在本类中添加该接口,保存运行,报错依旧。慌了,按道理没道理啊,之前项目也是直接这样引依赖,建个RedisConfig类就行了啊,然后就打开百度......

结果还百度不出......(估计是没有人连这种问题需要百度,所以搜不到)

好,言归正传,问题就如上述所说,没有默认够构造器,也就是无参构造器。

我依稀记得大学教我java的老师,说到构造器时,反复强调,无论你建多少个有参构造器,都必须带上无参构造器,毕业后其实一直遵守老师所说的,每次建造构造方法时,都会建无参构造方法,lombok的 @AllArgsConstructor@NoArgsConstructor我一直都是连着用的。这次没用不是因为忘记了,而是SpringSecurity中自带的UserDetails实现类org.springframework.security.core.userdetails.User 本身就没带无参构造器,并且,其中的类属性还带上了final关键字,意思是在声明时或者构造方法中必须定义初始值。

好嘛,SpringSecurity默认的User都没问题,我自定义的SecurityUser仿照应该问题也不大。

然后就出这档子事儿了。

扯远了,总而言之啊,就是spring中redis的反序列化需要依赖无参构造器

3. 问题解决

那就加上无参构造器呗,SpringSecurity的自定义的SecurityUser还需要将对象属性的final关键字去掉。

java 复制代码
public class SecurityUser implements UserDetails{

    private static final long serialVersionUID = 1L;

    private String userId;
    private String password;
    private String username;
    private Set<GrantedAuthority> authorities;
    private boolean accountNonExpired;
    private boolean accountNonLocked;
    private boolean credentialsNonExpired;
    private boolean enabled;
    
    /**
     * 无参构造器
     */
    public SecurityUser(){}

    /**
     * Simple Param Constructor
     * @param userId 用户id
     * @param password  用户密码
     * @param username  用户名
     * @param authorities   权限列表
     */
    public SecurityUser(String userId, String username, String password, Set<GrantedAuthority> authorities) {
        this(userId,username,password,authorities,
                true,true,true,true);
    }

    /**
     * AllParamConstructor
     * @param userId 用户id
     * @param password  用户密码
     * @param username  用户名
     * @param authorities   权限列表
     * @param accountNonExpired 账号没过期
     * @param accountNonLocked  账号没被锁
     * @param credentialsNonExpired 凭证没过期
     * @param enabled   正常
     */
    public SecurityUser(String userId, String username, String password, Set<GrantedAuthority> authorities,
                        boolean accountNonExpired, boolean accountNonLocked,
                        boolean credentialsNonExpired, boolean enabled) {
        this.userId = userId;
        this.username = username;
        this.password = password;
        this.authorities = Collections.unmodifiableSet(authorities);
        this.accountNonExpired = accountNonExpired;
        this.accountNonLocked = accountNonLocked;
        this.credentialsNonExpired = credentialsNonExpired;
        this.enabled = enabled;
    }
    // other todo
}

一点点题外话

作者还没做过什么大型项目,单体应用上看,前后端分离的情况下SpringSecurity的认证和授权根本上就是两个Filter和AOP做注解鉴权就行,感觉没有必要用SpringSecurity,之前用的shiro,也用过sa-token,相比之下,SpringSecurity是真的复杂,前后端分离情况下,SpringSecurity的UserDetailsService也拉,不好做缓存认证。

说到SpringSecurity的认证,网上很多方案都是使用jwt做token认证标识,对于jwt做下线功能该怎么做呢,jwt一旦颁发就只能到期失效。这样token被盗用的话一点办法都没有。有人说在缓存或数据库中添加signature的加密串,或者用账户密码做加密串,这样下线时或者更改密码时修改加密串就行......这样做确实能解决jwt的失效问题,但是jwt的主要特点(优点)就是无状态,每次认证只需要依赖jwt本体就行,这样数据库或者缓存添加jwt的加密串,岂不是违背了原本jwt的初衷?这样和使用普通token,用token做key缓存用户登录状态信息有什么区别。

虽然言语略带偏激,但是确实是心中疑问,有朋友看到且有见解的话,还请指教一下。

相关推荐
指尖下的技术6 分钟前
Mysql面试题----为什么B+树比B树更适合实现数据库索引
数据结构·数据库·b树·mysql
计算机-秋大田10 分钟前
基于微信小程序的汽车保养系统设计与实现(LW+源码+讲解)
spring boot·后端·微信小程序·小程序·课程设计
数据馅11 分钟前
python自动生成pg数据库表对应的es索引
数据库·python·elasticsearch
峰子201229 分钟前
B站评论系统的多级存储架构
开发语言·数据库·分布式·后端·golang·tidb
milk_yan2 小时前
MinIO的安装与使用
linux·数据仓库·spring boot
浏览器爱好者2 小时前
如何使用MongoDB进行数据存储?
数据库·mongodb
yuanpan2 小时前
MongoDB中的横向扩容数据分片
数据库·mongodb
草明2 小时前
Mongodb 慢查询日志分析 - 1
数据库·python·mongodb
yuanpan2 小时前
MongoDB的事务机制
数据库·mongodb
SelectDB3 小时前
Apache Doris 2.1.8 版本正式发布
大数据·数据库·数据分析