用redis存session时想用Json做序列化,遇到坑来记录一下
首先说下坑:
Spring-Security下面有些类是没有无参构造方法的,反序列化时会抛异常
- Spring Security
spring security配置,不是本文重点,之后再详细记录
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserServiceImpl userDetailService;
@Override
protected void configure(HttpSecurity http) throws Exception {
// 关闭csrf和frameOptions,如果不关闭会影响前端请求接口(这里不展开细讲了,感兴趣的自行了解)
http.csrf().disable();
http.headers().frameOptions().disable();
// 开启跨域以便前端调用接口
http.cors();
// 这是配置的关键,决定哪些接口开启防护,哪些接口绕过防护
http.authorizeRequests()
// 注意这里,是允许前端跨域联调的一个必要配置
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
// 指定某些接口不需要通过验证即可访问。登陆、注册接口肯定是不需要认证的
.antMatchers("/API/login", "/API/register","/","/login").permitAll()
// 这里意思是其它所有接口需要认证才能访问
.anyRequest().authenticated()
// 指定认证错误处理器
.and().exceptionHandling().authenticationEntryPoint(new MyEntryPoint());
}
@Override
public void configure(WebSecurity web) {
//对于在header里面增加token等类似情况,放行所有OPTIONS请求。
web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailService).passwordEncoder(passwordEncoder());
}
@Bean
@Override
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new PasswordEncoder() {
@Override
public String encode(CharSequence charSequence) {
return charSequence.toString();
}
@Override
public boolean matches(CharSequence charSequence, String s) {
return charSequence.toString().equals(s);
}
};
}
}
接下来是spring-session配置
这里主要是用GenericJackson2JsonRedisSerializer代替里spring-session-redis默认的Serializer,用SecurityJackson2Modules解决无默认构造函数无法反序列化的问题。
@Configuration
public class HttpSessionConfig implements BeanClassLoaderAware {
private ClassLoader loader;
@Bean
public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
return new GenericJackson2JsonRedisSerializer(objectMapper());
}
private ObjectMapper objectMapper(){
ObjectMapper mapper = new ObjectMapper();
mapper.registerModules(SecurityJackson2Modules.getModules(this.loader));
return mapper;
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.loader = classLoader;
}
}