xkcoding/spring-boot-demo · error · ResourceAccessException
请求错误,用户尚未登录
Error message
请求错误,用户尚未登录
What it means
Thrown by the OAuth logout endpoint when the Principal parameter is null — meaning no authenticated user session exists at the time of the GET /oauth/logout request. The exception type used is ResourceAccessException (Spring's web-client I/O exception), which is semantically wrong for an authentication-state problem; it should be an auth-related exception. This mismatch means Spring's exception handling may route it incorrectly.
Source
Thrown at demo-oauth/oauth-authorization-server/src/main/java/com/xkcoding/oauth/controller/Oauth2Controller.java:45
*
* @return view
*/
@GetMapping("/login")
public String loginView() {
return "login";
}
/**
* 退出登录
*
* @param redirectUrl 退出完成后的回调地址
* @param principal 用户信息
* @return 结果
*/
@GetMapping("/logout")
public ModelAndView logoutView(@RequestParam("redirect_url") String redirectUrl, Principal principal) {
if (Objects.isNull(principal)) {
throw new ResourceAccessException("请求错误,用户尚未登录");
}
ModelAndView view = new ModelAndView();
view.setViewName("logout");
view.addObject("user", principal.getName());
view.addObject("redirectUrl", redirectUrl);
return view;
}
}
View on GitHub (pinned to 87a142f960)
Solutions
- Redirect unauthenticated users to the login page instead of throwing an exception.
- Replace ResourceAccessException with an appropriate auth exception (e.g., BadCredentialsException or a custom UnauthorizedException) to match the semantic.
- Add Spring Security configuration to require authentication on /oauth/logout so the endpoint is never reached without a Principal.
Example fix
// before
if (Objects.isNull(principal)) {
throw new ResourceAccessException("请求错误,用户尚未登录");
}
// after — redirect to login instead of throwing a client-access exception
if (Objects.isNull(principal)) {
ModelAndView view = new ModelAndView();
view.setViewName("redirect:/oauth/login");
return view;
} Defensive patterns
Strategy: validation
Validate before calling
// Check authentication state before calling logoutView
// In Spring Security config, require authentication on /oauth/logout:
// .antMatchers("/oauth/logout").authenticated()
// This ensures Principal is never null at the controller.
// Alternatively, check in a filter:
if (SecurityContextHolder.getContext().getAuthentication() == null ||
!SecurityContextHolder.getContext().getAuthentication().isAuthenticated()) {
// redirect to login
} Try / catch
// In a @ControllerAdvice handler — note ResourceAccessException is semantically wrong here
@ExceptionHandler(ResourceAccessException.class)
public String handleResourceAccessException(ResourceAccessException e) {
log.warn("Resource access error: {}", e.getMessage());
return "redirect:/oauth/login";
} Prevention
- Configure Spring Security to require authentication on /oauth/logout so Principal is always non-null.
- Use a redirect to login instead of throwing an exception for unauthenticated access.
- Do not use ResourceAccessException for auth-state problems — it is meant for REST client I/O failures.
When it happens
Trigger: Navigating to GET /oauth/logout?redirect_url=... without an active OAuth session (Principal injected by Spring Security is null). This happens when the session expired, the user was never authenticated, or the security context was cleared.
Common situations: Session timeout before clicking logout; accessing the logout URL directly without logging in first; Spring Security session management misconfigured so Principal is not injected; browser cache serving the logout link post-expiry.
Related errors
AI-assisted analysis of xkcoding/spring-boot-demo@87a142f960 (2026-08-14).
Data as JSON: /api/errors/3e30803584df411c.
Report an issue: GitHub.