1. Overview
1.概述
Spring Security handles receiving and parsing authentication credentials for us.
Spring Security为我们处理接收和解析认证凭证。
In this short tutorial, we’re going to look at how to get the SecurityContext information from a request, within our handler code.
在这个简短的教程中,我们将看看如何在我们的处理程序代码中从一个请求中获取SecurityContext信息。
2. The @CurrentSecurityContext Annotation
2.@CurrentSecurityContext 注释
We could use some boilerplate code to read the security context:
我们可以使用一些模板代码来读取安全环境。
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();
However, there is now a @CurrentSecurityContext annotation to help us.
然而,现在有一个@CurrentSecurityContext注解来帮助我们。
Furthermore, using annotations makes the code more declarative and makes the authentication object injectable. With @CurrentSecurityContext, we can also access the Principal implementation of the current user.
此外,使用注解使代码更具声明性,并使authentication对象可注入。通过@CurrentSecurityContext,我们还可以访问当前用户的Principal实现。
In the examples below, we’re going to look at a couple of ways to get security context data, like the Authentication and the name of the Principal. We’ll also see how to test our code.
在下面的例子中,我们将看一下获得安全上下文数据的几种方法,比如Authentication和Principal的名字。我们还将看到如何测试我们的代码。
3. Maven Dependencies
3.Maven的依赖性
If we have a recent version of Spring Boot, then we need only to include the dependency for spring-boot-starter-security:
如果我们有最新版本的Spring Boot,那么我们只需要包含spring-boot-starter-security的依赖性:。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
Otherwise, we can upgrade spring-security-core to a minimum version of 5.2.1.RELEASE:
否则,我们可以将spring-security-core升级到最低版本5.2.1.RELEASE。
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>5.2.1.RELEASE</version>
</dependency>
4. Implementing with @CurrentSecurityContext
4.用@CurrentSecurityContext实现
We can use SpEL (Spring Expression Language) with @CurrentSecurityContext to inject the Authentication object or the Principal. SpEL works together with type lookup. The type check is not enforced by default, but we can enable it via the errorOnInvalidType parameter of the @CurrentSecurityContext annotation.
我们可以使用SpEL(Spring表达式语言)与@CurrentSecurityContext来注入Authentication对象或Principal。SpEL与类型检查一起工作。默认情况下不执行类型检查,但我们可以通过@CurrentSecurityContext注解的errorOnInvalidType参数来启用它。
4.1. Obtaining the Authentication Object
4.1.获取Authentication对象
Let’s read the Authentication object so that we can return its details:
让我们读一下Authentication对象,以便我们可以返回它的细节。
@GetMapping("/authentication")
public Object getAuthentication(@CurrentSecurityContext(expression = "authentication")
Authentication authentication) {
return authentication.getDetails();
}
Note that the SpEL expression refers to the authentication object itself.
注意,SpEL表达式指的是认证对象本身。
Let’s test it:
让我们来测试一下。
@Test
public void givenOAuth2Context_whenAccessingAuthentication_ThenRespondTokenDetails() {
ClientCredentialsResourceDetails resourceDetails =
getClientCredentialsResourceDetails("baeldung", singletonList("read"));
OAuth2RestTemplate restTemplate = getOAuth2RestTemplate(resourceDetails);
String authentication = executeGetRequest(restTemplate, "/authentication");
Pattern pattern = Pattern.compile("\\{\"remoteAddress\":\".*"
+ "\",\"sessionId\":null,\"tokenValue\":\".*"
+ "\",\"tokenType\":\"Bearer\",\"decodedDetails\":null}");
assertTrue("authentication", pattern.matcher(authentication).matches());
}
We should note that, in this example, we’re getting all the details of our connection. As our test code cannot predict the remoteAddress or tokenValue, we’re using a regular expression to check the resulting JSON.
我们应该注意到,在这个例子中,我们得到的是我们连接的所有细节。由于我们的测试代码无法预测remoteAddress或tokenValue,我们使用正则表达式来检查结果的JSON。
4.2. Obtaining the Principal
4.2.获得Principal
If we only want the Principal from our authentication data, we can change the SpEL expression and the injected object:
如果我们只想要认证数据中的Principal,我们可以改变SpEL表达式和注入的对象。
@GetMapping("/principal")
public String getPrincipal(@CurrentSecurityContext(expression = "authentication.principal")
Principal principal) {
return principal.getName();
}
In this case, we’re returning only the Principal name using the getName method.
在这种情况下,我们使用getName方法只返回Principal名称。
Let’s test it:
让我们来测试一下。
@Test
public void givenOAuth2Context_whenAccessingPrincipal_ThenRespondBaeldung() {
ClientCredentialsResourceDetails resourceDetails =
getClientCredentialsResourceDetails("baeldung", singletonList("read"));
OAuth2RestTemplate restTemplate = getOAuth2RestTemplate(resourceDetails);
String principal = executeGetRequest(restTemplate, "/principal");
assertEquals("baeldung", principal);
}
Here we see the name baeldung, which was added to the client credentials, being found and returned from inside the Principal object injected into the handler.
在这里,我们看到名字baeldung,它被添加到客户证书中,被发现并从注入处理程序的Principal对象中返回。
5. Conclusion
5.总结
In this article, we’ve seen how to access properties within the current security context and inject them into parameters in our handler methods.
在这篇文章中,我们看到了如何访问当前安全上下文中的属性,并将它们注入处理方法中的参数。
We’ve done this by taking advantage of SpEL and the @CurrentSecurityContext annotation.
我们通过利用SpEL和@CurrentSecurityContext注解来做到这一点。
As always, the full source code for the examples is available over on GitHub.
一如既往,这些示例的完整源代码可在GitHub上获得over。