目录
一、问题简述
今天新开的一个项目遇到了点问题,本来是一个简单的前后端分离的项目,但是需求是要求对应两个前端项目,并且token都是独立的,然后加了一个 spring security配置,结果发现新前端的get请求访问没问题,但是post请求无法访问,最后发现少配置了一个东西。
二、问题解决
添加了JWT filter
// 添加JWT filter
httpSecurity.csrf().disable().headers().frameOptions().disable();
三、完整spring security配置
1.spring security配置
/**
* spring security配置
*/
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class AuthTokenSecurity extends WebSecurityConfigurerAdapter {
/** 自定义用户认证逻辑 */
@Resource
private UserDetailsService userDetailsService;
/** 退出处理类 */
@Resource
private AuthTokenLogout logoutSuccessHandler;
/** token认证过滤器 */
@Resource
private AuthTokenFilter authTokenFilter;
/** 认证失败处理类 */
@Resource
private AuthTokenEntryPoint authTokenEntryPoint;
/** 跨域过滤器 */
@Resource
private CorsFilter corsFilter;
/**
* 解决 无法直接注入 AuthenticationManager
* @throws Exception
*/
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
/**
* 跨域配置
*/
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
// 设置访问源地址
config.addAllowedOriginPattern("*");
// 设置访问源请求头
config.addAllowedHeader("*");
// 设置访问源请求方法
config.addAllowedMethod("*");
// 对接口配置跨域设置
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity .csrf().disable() .headers().frameOptions().disable();
// 退出处理类
httpSecurity.logout().logoutUrl("/core/logout").logoutSuccessHandler(logoutSuccessHandler);
// 认证失败处理类
httpSecurity.exceptionHandling().authenticationEntryPoint(authTokenEntryPoint);
// 添加JWT filter
httpSecurity.addFilterBefore(authTokenFilter, UsernamePasswordAuthenticationFilter.class);
// 添加CORS filter
httpSecurity.addFilterBefore(corsFilter, AuthTokenFilter.class);
httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);
httpSecurity.sessionManagement().maximumSessions(1)
.maxSessionsPreventsLogin(true)
.sessionRegistry(sessionRegistry());
}
/**
* 强散列哈希加密实现
*/
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
/**
* 身份认证接口
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
}
2.退出处理类
@Configuration
public class AuthTokenLogout implements LogoutSuccessHandler {
@Resource
private TokenService tokenService;
@Resource
private RocketMQTemplate rocketMQTemplate;
/**
* 退出处理
*/
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
LoginUser loginUser = tokenService.getLoginUser(request);
if (StringUtil.isNotNull(loginUser)) {
// 删除用户缓存记录
tokenService.delRedisToken(loginUser.getTokenUuid());
// 记录日志
rocketMQTemplate.convertAndSend(ConstantsPro.CORE_MQ_LOG_LOGIN, LogLogin.genLoginLog(loginUser.getUser().getUserId(), Constants.LOGOUT, "退出成功"));
}
ServletUtil.renderString(response, JSON.toJSONString(AjaxResult.error(ContantsHttp.SUCCESS, "退出成功")));
}
}
3.认证失败处理类
@Component
public class AuthTokenEntryPoint implements AuthenticationEntryPoint, Serializable {
private static final long serialVersionUID = -8970718410437077606L;
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) {
ServletUtil.renderString(response, JSON.toJSONString(AjaxResult.error(ContantsHttp.UNAUTHORIZED, "请求访问:" + request.getRequestURI() + ",认证失败,无法访问系统资源")));
}
}