From fee6a9bb0e263706614565c830de51dbf4b603aa Mon Sep 17 00:00:00 2001 From: songhee Date: Wed, 14 Jan 2026 17:05:53 +0900 Subject: [PATCH] docs: add CurrentSecurityContext section and link references Signed-off-by: songhee --- .../servlet/authentication/anonymous.adoc | 3 +- .../servlet/authentication/architecture.adoc | 6 +- .../ROOT/pages/servlet/integrations/mvc.adoc | 66 +++++++++++++++++++ 3 files changed, 73 insertions(+), 2 deletions(-) diff --git a/docs/modules/ROOT/pages/servlet/authentication/anonymous.adoc b/docs/modules/ROOT/pages/servlet/authentication/anonymous.adoc index aac99a58b0..38080021cd 100644 --- a/docs/modules/ROOT/pages/servlet/authentication/anonymous.adoc +++ b/docs/modules/ROOT/pages/servlet/authentication/anonymous.adoc @@ -137,7 +137,8 @@ fun method(authentication: Authentication?): String { will always return "not anonymous", even for anonymous requests. The reason is that Spring MVC resolves the parameter using `HttpServletRequest#getPrincipal`, which is `null` when the request is anonymous. -If you'd like to obtain the `Authentication` in anonymous requests, use `@CurrentSecurityContext` instead: +If you'd like to obtain the `Authentication` in anonymous requests, use +xref:servlet/integrations/mvc.adoc#mvc-current-security-context[`@CurrentSecurityContext`] instead: .Use CurrentSecurityContext for Anonymous requests [tabs] diff --git a/docs/modules/ROOT/pages/servlet/authentication/architecture.adoc b/docs/modules/ROOT/pages/servlet/authentication/architecture.adoc index b181fa9635..ec7019b886 100644 --- a/docs/modules/ROOT/pages/servlet/authentication/architecture.adoc +++ b/docs/modules/ROOT/pages/servlet/authentication/architecture.adoc @@ -97,7 +97,11 @@ val authorities = authentication.authorities ---- ====== -// FIXME: Add links to and relevant description of HttpServletRequest.getRemoteUser() and @CurrentSecurityContext @AuthenticationPrincipal +In Spring MVC, you can resolve the current principal with +xref:servlet/integrations/mvc.adoc#mvc-authentication-principal[`@AuthenticationPrincipal`] +and the full `SecurityContext` with +xref:servlet/integrations/mvc.adoc#mvc-current-security-context[`@CurrentSecurityContext`]. +For Servlet API access, use `HttpServletRequest#getRemoteUser`. By default, `SecurityContextHolder` uses a `ThreadLocal` to store these details, which means that the `SecurityContext` is always available to methods in the same thread, even if the `SecurityContext` is not explicitly passed around as an argument to those methods. Using a `ThreadLocal` in this way is quite safe if you take care to clear the thread after the present principal's request is processed. diff --git a/docs/modules/ROOT/pages/servlet/integrations/mvc.adoc b/docs/modules/ROOT/pages/servlet/integrations/mvc.adoc index 92223407e2..f3deb9ffa1 100644 --- a/docs/modules/ROOT/pages/servlet/integrations/mvc.adoc +++ b/docs/modules/ROOT/pages/servlet/integrations/mvc.adoc @@ -624,6 +624,72 @@ open fun findMessagesForUser(@CurrentUser("user_id") userId: String?): ModelAndV ---- ====== +[[mvc-current-security-context]] +== @CurrentSecurityContext + +Spring Security provides `CurrentSecurityContextArgumentResolver`, which can automatically resolve the current `SecurityContext` for Spring MVC arguments. +By using `@EnableWebSecurity`, you automatically have this added to your Spring MVC configuration. +If you use XML-based configuration, you must add this yourself: + +[source,xml] +---- + + + + + +---- + +Once `CurrentSecurityContextArgumentResolver` is configured, you can access the `SecurityContext` directly: + +[tabs] +====== +Java:: ++ +[source,java,role="primary"] +---- +@GetMapping("/me") +public String me(@CurrentSecurityContext SecurityContext context) { + return context.getAuthentication().getName(); +} +---- + +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +@GetMapping("/me") +fun me(@CurrentSecurityContext context: SecurityContext): String { + return context.authentication.name +} +---- +====== + +You can also use a SpEL expression that is rooted at the `SecurityContext`: + +[tabs] +====== +Java:: ++ +[source,java,role="primary"] +---- +@GetMapping("/me") +public String me(@CurrentSecurityContext(expression = "authentication") Authentication authentication) { + return authentication.getName(); +} +---- + +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +@GetMapping("/me") +fun me(@CurrentSecurityContext(expression = "authentication") authentication: Authentication): String { + return authentication.name +} +---- +====== + [[mvc-async]] == Spring MVC Async Integration