Spring Security整合过程中,User类实现UserDetails接口,存入Redis,反序列化报错问题。

文章讲述了在整合SpringSecurity时,如何将登录成功的用户信息存储到Redis中,遇到的序列化问题及解决方案,即在User类上添加`@JsonIgnoreProperties(ignoreUnknown=true)`和`@JsonIgnore`注解以解决异常。

最近在整合Spring Security过程中,登陆成功后想把获取到的用户信息存入Redis。其中User类实现了UserDetails接口。

User类如下:


@Data
@NoArgsConstructor
@AllArgsConstructor
public class LoginUser implements UserDetails {

    //用户信息
    private SysUser sysUser;
    //用户权限集合
    private List<String> permissions;

    private List<SimpleGrantedAuthority> authorities;

    public LoginUser(SysUser sysUser,List<String> permissions){
        this.sysUser = sysUser;
        this.permissions = permissions;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        if(authorities != null){
            return authorities;
        }
        authorities = this.permissions.stream().map(SimpleGrantedAuthority ::new).collect(Collectors.toList());
        return authorities;
    }

    @Override
    public String getPassword() {
        return sysUser.getPassword();
    }

    @Override
    public String getUsername() {
        return sysUser.getUserName();
    }

    @Override
    public boolean isAccountNonExpired() {
        return sysUser.getAccountNotExpired();
    }

    @Override
    public boolean isAccountNonLocked() {
        return sysUser.getAccountNotLocked();
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return sysUser.getCredentialsNotExpired();
    }

    @Override
    public boolean isEnabled() {
        return sysUser.getEnabled();
    }
}

登陆成功后要把用户信息存入Redis,此时就会报错如下:

Caused by: org.springframework.data.redis.serializer.SerializationException: Cannot deserialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; nested exception is java.io.InvalidClassException: weixin.popular.bean.token.Token; local class incompatible: stream classdesc serialVersionUID = -584152862903853930, local class serialVersionUID = 8841433872811285796

此时只要在LoginUser类中加入以下注解,即可解决:

@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class LoginUser implements UserDetails {

    //用户信息
    private SysUser sysUser;
    //用户权限集合
    private List<String> permissions;

    @JsonIgnore
    private List<SimpleGrantedAuthority> authorities;

    public LoginUser(SysUser sysUser,List<String> permissions){
        this.sysUser = sysUser;
        this.permissions = permissions;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        if(authorities != null){
            return authorities;
        }
        authorities = this.permissions.stream().map(SimpleGrantedAuthority ::new).collect(Collectors.toList());
        return authorities;
    }

    @Override
    public String getPassword() {
        return sysUser.getPassword();
    }

    @Override
    public String getUsername() {
        return sysUser.getUserName();
    }

    @Override
    public boolean isAccountNonExpired() {
        return sysUser.getAccountNotExpired();
    }

    @Override
    public boolean isAccountNonLocked() {
        return sysUser.getAccountNotLocked();
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return sysUser.getCredentialsNotExpired();
    }

    @Override
    public boolean isEnabled() {
        return sysUser.getEnabled();
    }
}

class上加上

@JsonIgnoreProperties(ignoreUnknown = true)

在属性上加入

@JsonIgnore

完美解决

<think>嗯,用户想了解Spring Security框架中的UserDetails接口的作用。首先,我需要回忆一下自己对这个接口的理解。记得UserDetailsSpring Security中的一个核心接口,用来表示用户信息。可能和认证授权有关? 然后,用户可能是在使用Spring Security进行用户认证时遇到了问题,或者想了解如何自定义用户信息。需要详细解释UserDetails的作用,以及它在框架中的位置。 接下来,应该先介绍UserDetails的基本作用,比如它封装了用户的基本信息和权限。然后说明它的方法,比如getUsername(), getPassword(), getAuthorities()等。还要提到用户需要实现这个接口来自定义用户模型,或者通过UserDetailsService来加载用户数据。 可能还需要比较UserDetailsUserDetailsService的关系,说明UserDetailsService负责加载用户数据,返回UserDetails实例。这样用户就能理解整个认证流程的组成部分。 另外,要注意提到UserDetails的一些实现,比如User,方便用户直接使用。同时,强调扩展性,用户可以根据需求实现自己的UserDetails,比如添加额外字段。 需要确保语言通俗易懂,结构清晰,分点说明。可能用户是刚开始接触Spring Security,所以避免使用过于专业的术语,或者对术语进行解释。比如,认证和授权的区别可能需要简单说明。 还有,用户的问题可能涉及到如何在实际项目中应用UserDetails,所以可以举一个简单的例子,比如自定义用户实体实现UserDetails接口,并重写相关方法。或者提到常见的用法,比如结合数据库查询用户信息。 需要检查是否有遗漏的关键点,比如UserDetails的方法必须正确实现,特别是getAuthorities()返回用户的权限集合,这关系到权限控制。如果返回空的权限,可能导致用户无法访问资源。 还要注意安全性的问题,比如密码的正确处理,是否启用账户状态等。比如isAccountNonExpired()等方法需要根据实际情况返回,以确保账户状态检查生效。 总结下来,回答应该包括:UserDetails的作用、方法说明、与UserDetailsService的关系、实现方式、示例以及注意事项。确保覆盖用户可能关心的各个方面,帮助用户理解该接口Spring Security中的重要性。</think>Spring Security中的`UserDetails`接口是框架的核心组件之一,**主要用于封装用户信息和权限**。以下是逐步说明其作用及关键点: --- ### 一、核心作用 1. **用户信息标准化** `UserDetails`定义了用户的核心属性(如用户名、密码、权限等),**统一了用户数据的表示方式**,使Spring Security能够以标准化流程处理认证和授权。 2. **权限管理** 通过`getAuthorities()`方法返回用户的权限集合(如角色`ROLE_ADMIN`或操作权限`READ`),**决定用户可访问的资源**。 3. **账户状态控制** 提供`isAccountNonExpired()`、`isEnabled()`等方法,**验证账户是否有效**(如是否未过期、未被锁定)。 --- ### 二、接口方法详解 `UserDetails`包含以下必须实现的方法: ```java public interface UserDetails extends Serializable { // 获取用户权限集合 Collection<? extends GrantedAuthority> getAuthorities(); // 获取密码(通常加密后) String getPassword(); // 获取用户名 String getUsername(); // 账户是否未过期 boolean isAccountNonExpired(); // 账户是否未锁定 boolean isAccountNonLocked(); // 密码是否未过期 boolean isCredentialsNonExpired(); // 账户是否启用 boolean isEnabled(); } ``` --- ### 三、与`UserDetailsService`的关系 - **分工协作** - `UserDetailsService`负责**加载用户数据**(如从数据库查询),返回一个`UserDetails`实例。 - `UserDetails`则**承载具体用户信息**,供认证流程使用。 - **典型流程示例** ```java public class CustomUserDetailsService implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) { // 1. 查询数据库或其他存储 User user = userRepository.findByUsername(username); // 2. 返回UserDetails实例(如Spring提供的User) return new org.springframework.security.core.userdetails.User( user.getUsername(), user.getPassword(), user.getAuthorities() ); } } ``` --- ### 四、常见实现方式 1. **使用内置的`User`** Spring Security提供了`User`(`UserDetails`的实现),可直接用于简单场景: ```java UserDetails user = User.withUsername("admin") .password("{bcrypt}加密后的密码") .roles("ADMIN") .build(); ``` 2. **自定义实现** 若需扩展用户信息(如添加`email`字段),可**自定义实现`UserDetails`接口**: ```java public class CustomUser implements UserDetails { private String username; private String password; private String email; // 扩展字段 // 实现所有接口方法 @Override public Collection<? extends GrantedAuthority> getAuthorities() { return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")); } // 其他方法(如isAccountNonExpired等)根据业务需求返回 } ``` --- ### 五、注意事项 1. **密码安全性** 确保密码存储为**加密格式**(如BCrypt),避免明文存储。 2. **权限的粒度控制** 权限应细化到具体操作(如`READ:FILE`),而不仅仅是角色。 3. **账户状态检查** 根据业务需求正确实现`isEnabled()`等方法,否则可能导致账户异常状态失效。 --- ### 六、总结 `UserDetails`接口Spring Security中**连接用户数据与安全机制的核心桥梁**。通过标准化用户属性和权限,它为认证授权提供了统一的基础模型,开发者可通过灵活扩展满足不同业务需求。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值