项目场景:
项目集成spring security
,测试自定义的退出方法,结果与预期不符。
问题描述
自定义了退出方法logout
,测试时控制台打印的日志显示NONE_PROVIDED(String)
,返回结果提示未登录
(自定义了AuthenticationEntryPoint
)。
控制台打印结果:
2023-02-25 14:06:03.893 DEBUG 48388 --- [nio-8080-exec-6] com.example.hours.dao.UserDao.selectOne : ==> Preparing: SELECT id,nickname,password,mobile,sign,email,header,gender,authority,del_flag,create_time,update_time FROM user WHERE del_flag=0 AND (nickname = ?)
2023-02-25 14:06:03.893 DEBUG 48388 --- [nio-8080-exec-6] com.example.hours.dao.UserDao.selectOne : ==> Parameters: NONE_PROVIDED(String)
2023-02-25 14:06:03.894 DEBUG 48388 --- [nio-8080-exec-6] com.example.hours.dao.UserDao.selectOne : <== Total: 0
自定义 AuthenticationEntryPoint,处理未登录情况
/**
* 用户未登录
*/
@Component
public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
// ResultCodeEnum.UNAUTHORIZED(401, "暂未登录或token已经过期")
Result<Object> failedResult = Result.failed(ResultCodeEnum.UNAUTHORIZED);
String s = JSON.toJSONString(failedResult);
WebUtils.renderString(response, s);
}
}
原因分析:
返回结果发现是
ResultCodeEnum.UNAUTHORIZED
,可以确定走了自定义的login
方法。
接下来从自定义的JwtAuthenticationTokenFilter
开始 debug,一直到过滤器链走完,依然没找到原因,观察整个过滤器链,决定从LogoutFilter
开始调试,
当执行到this.logoutSuccessHandler.onLogoutSuccess(request, response, auth);
时,调用了SimpleUrlLogoutSuccessHandler
的onLogoutSuccess
方法,
继续进入,发现调用了AbstractAuthenticationTargetUrlRequestHandler
的handle
方法,
观察targetUrl
,发现其值为/login?logout
,接下来看到sendRedirect
,就找到原因了,在这里重定向到了/login
(如果配置了loginPage,则重定向到loginPage),随后发起了登录请求,所以最后结果提示未登录。
解决方案:
方案一:
更改请求地址,将@PostMapping("/logout")
改成@PostMapping("/my_logout")
。