{"record":{"id":"3e30803584df411c","repo":"xkcoding/spring-boot-demo","slug":"error-3e3080","errorCode":null,"errorMessage":"请求错误，用户尚未登录","messagePattern":"请求错误，用户尚未登录","errorType":"exception","errorClass":"ResourceAccessException","httpStatus":null,"severity":"error","filePath":"demo-oauth/oauth-authorization-server/src/main/java/com/xkcoding/oauth/controller/Oauth2Controller.java","lineNumber":45,"sourceCode":"     *\n     * @return view\n     */\n    @GetMapping(\"/login\")\n    public String loginView() {\n        return \"login\";\n    }\n\n    /**\n     * 退出登录\n     *\n     * @param redirectUrl 退出完成后的回调地址\n     * @param principal   用户信息\n     * @return 结果\n     */\n    @GetMapping(\"/logout\")\n    public ModelAndView logoutView(@RequestParam(\"redirect_url\") String redirectUrl, Principal principal) {\n        if (Objects.isNull(principal)) {\n            throw new ResourceAccessException(\"请求错误，用户尚未登录\");\n        }\n        ModelAndView view = new ModelAndView();\n        view.setViewName(\"logout\");\n        view.addObject(\"user\", principal.getName());\n        view.addObject(\"redirectUrl\", redirectUrl);\n        return view;\n    }\n\n}\n","sourceCodeStart":27,"sourceCodeEnd":55,"githubUrl":"https://github.com/xkcoding/spring-boot-demo/blob/87a142f9604c1a5365b4d24d22c2c11c26a9d5ab/demo-oauth/oauth-authorization-server/src/main/java/com/xkcoding/oauth/controller/Oauth2Controller.java#L27-L55","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nif (Objects.isNull(principal)) {\n    throw new ResourceAccessException(\"请求错误，用户尚未登录\");\n}\n\n// after — redirect to login instead of throwing a client-access exception\nif (Objects.isNull(principal)) {\n    ModelAndView view = new ModelAndView();\n    view.setViewName(\"redirect:/oauth/login\");\n    return view;\n}","handlingStrategy":"validation","validationCode":"// Check authentication state before calling logoutView\n// In Spring Security config, require authentication on /oauth/logout:\n// .antMatchers(\"/oauth/logout\").authenticated()\n// This ensures Principal is never null at the controller.\n\n// Alternatively, check in a filter:\nif (SecurityContextHolder.getContext().getAuthentication() == null ||\n    !SecurityContextHolder.getContext().getAuthentication().isAuthenticated()) {\n    // redirect to login\n}","typeGuard":null,"tryCatchPattern":"// In a @ControllerAdvice handler — note ResourceAccessException is semantically wrong here\n@ExceptionHandler(ResourceAccessException.class)\npublic String handleResourceAccessException(ResourceAccessException e) {\n    log.warn(\"Resource access error: {}\", e.getMessage());\n    return \"redirect:/oauth/login\";\n}","preventionTips":["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."],"tags":["oauth","spring-security","authentication","session","logout","exception-misuse"],"backgroundTag":null,"analyzedSha":"87a142f9604c1a5365b4d24d22c2c11c26a9d5ab","analyzedAt":"2026-08-14T01:16:58.217Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}