Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
66 changes: 66 additions & 0 deletions docs/modules/ROOT/pages/servlet/integrations/mvc.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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]
----
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="org.springframework.security.web.method.annotation.CurrentSecurityContextArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
----

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

Expand Down
Loading