我有一个配置了弹簧安全性的应用程序
一切都在运作。
UserDetailService是:
@Service(value = "userDetail")
public class UserDetailServiceImpl implements UserDetailsService, Serializable {
private static final long serialVersionUID = 3487495895819392L;
@Autowired
private IUserDetailRepository iUserDetailRepository;
@Autowired
private IUserRoleRepository iUserRoleRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = iUserDetailRepository.loadUserByUsername(username);
List<UserRole> roles = iUserRoleRepository.getAllRoleByUserName(username);
UserDetails u = new UserDetails() {
@Override
public boolean isEnabled() {
// return user.getEnable();
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public String getUsername() {
// return user.getUsername();
return "reyhane";
}
@Override
public String getPassword() {
// return user.getPassword();
return "reyhane";
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> authorities = new ArrayList<>();
SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ADMIN");
authorities.add(authority);
return authorities;
}
};
return u;
}
}
之后我被迫在这个配置上配置spring会话,以便将Spring安全的上下文保存到Redis中 UserDetailService中存在问题 UserDetailService有两个自动装配的文件,如上所示:
@Autowired
private IUserDetailRepository iUserDetailRepository;
@Autowired
private IUserRoleRepository iUserRoleRepository;
这两个自动连接字段用于从DB获取用户和用户的角色信息 这里有趣的是,当我评论这两个自动装配时:
//@Autowired
private IUserDetailRepository iUserDetailRepository;
//@Autowired
private IUserRoleRepository iUserRoleRepository;
并手动填写用户和用户的角色.Spring会话也正常工作但是当这两个@Autowired
存在于类中时,会引发以下异常:
引起: org.springframework.core.serializer.support.SerializationFailedException: 无法使用DefaultSerializer序列化对象;嵌套异常 是java.io.NotSerializableException: org.springframework.dao.support.PersistenceExceptionTranslationInterceptor 在 org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:68) 〜[spring-core-4.3.2.RELEASE.jar:4.3.2.RELEASE] at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:35) 〜[spring-core-4.3.2.RELEASE.jar:4.3.2.RELEASE] at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize(JdkSerializationRedisSerializer.java:90) 〜[spring-data-redis-1.7.2.RELEASE.jar:na] ...省略了35个常用帧 引起:java.io.NotSerializableException: org.springframework.dao.support.PersistenceExceptionTranslationInterceptor 在 java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184) 〜[na:1.8.0_111] at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548) 〜[NA:1.8.0_111]
每个人都知道发生了什么? 我不明白发生了什么 我不知道谷歌搜索有什么关键 我想知道春季会议和春季安全之间会发生什么,以及如何解决它 谢谢你的帮助
答案 0 :(得分:3)
这实际上与这些依赖关系无关,这是因为您正在使用(非static
)内部类。您应该使用嵌入式static
类,或者只使用Spring Security中的常规User
类。 (有关内部,(非)静态嵌入类的更多信息,请参见this answer。
简而言之,由于您使用内部类的事实,它需要存在外部类的实例。现在,当序列化UserDetails
时,它也会尝试序列化外部类。
最简单的解决方案是重写代码并使用Spring Security提供的User
类(假设您使用的是Spring Security 4.2,您可以使用UserBuilder
)。
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = iUserDetailRepository.loadUserByUsername(username);
List<UserRole> roles = iUserRoleRepository.getAllRoleByUserName(username);
return User.withUsername(user.getUsername())
.password(user.getPassword())
.disabled(!user.getEnable())
.roles(roles.stream().map(<convert-to-SimpleGrantedAuthority>).collect(Collectors.toList()))
.build();
}
如果您在4.2之前使用Spring Security,则只需使用构造函数构造User
对象即可。
return new User(user.getUsername(), user.getPassword(), user.getEnable(), true, true, true, <convert-roles-to-SimpleGrantedAuthoritu>);
当返回一个具体类时,它不需要外部类的实例(因为它不是内部类),并且它不会尝试序列化它。它只会序列化User
而不会其他任何内容。
答案 1 :(得分:0)
我用这个解决方案解决了我的问题:
private static IUserDetailRepository userDetailRepository;
private static IUserRoleRepository userRoleRepository;
@Autowired
public void setUserDetailRepository(IUserDetailRepository userDetailRepository) {
UserDetailServiceImpl.userDetailRepository = userDetailRepository;
}
@Autowired
public void setUserRoleRepository(IUserRoleRepository userRoleRepository) {
UserDetailServiceImpl.userRoleRepository = userRoleRepository;
}