使用 @AuthenticationPrincipal 和 JwtAuthenticationToken 来使用自己的用户类

Wim*_*uwe 1 java spring-security spring-boot

我正在使用 Spring Boot 2.2.5 和 Spring Security 5.2.2 usingspring-security-oauth2-resource-serverspring-security-oauth2-jose依赖项。

在我的控制器方法中,我有这个工作:

@GetMapping
public ResponseEntity<?> doSomething(@AuthenticationPrincipal JwtAuthenticationToken principal) {
    User user = getUser(principal);
    ...
}
Run Code Online (Sandbox Code Playgroud)

principal被注入并包含在Azure上的用户(我使用Azure的AD B2C)的ID。

在每个方法中我需要做的第一件事是User使用这个User从我的userServiceSpring bean中检索 的私有方法来获取我自己的对象:

    private User getUser(JwtAuthenticationToken principal) {
        AuthorizationServerUserId authorizationServerUserId = AuthorizationServerUserId.fromPrincipal(principal);
        return userService.findByAuthorizationServerUserId(authorizationServerUserId)
                          .orElseThrow(() -> UserNotFoundException.forAuthorizationServerUserId(authorizationServerUserId));
    }
Run Code Online (Sandbox Code Playgroud)

如何配置 Spring (Boot) 以使其有效:

@GetMapping
public ResponseEntity<?> doSomething(@AuthenticationPrincipal User user) {

}
Run Code Online (Sandbox Code Playgroud)

目前安全配置是这样完成的:

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
                .authorizeRequests(registry -> {
                    registry.antMatchers("/registration/**").permitAll();

                    registry.antMatchers("/api/**").authenticated();
                });
    }
}
Run Code Online (Sandbox Code Playgroud)

Ele*_*ana 9

@AuthenticationPrincipal 接受一个 SpEL 表达式作为参数。

您可以User在提供的 SpEL 表达式中指定将主体转换为 a 的 bean 和方法。

@GetMapping
public ResponseEntity<?> doSomething(@AuthenticationPrincipal(expression = "@userService.getUser(#this)") User user) {

}
Run Code Online (Sandbox Code Playgroud)

whereuserService指的是UserService豆子。

您可以通过创建@AuthenticationPrincipal用作元注释的自定义注释来更进一步。

@Target({ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@AuthenticationPrincipal(expression = "@userService.getUser(#this)")
public @interface CurrentUser {}
Run Code Online (Sandbox Code Playgroud)

那么你的控制器就会变成

@GetMapping
public ResponseEntity<?> doSomething(@CurrentUser User user) {

}
Run Code Online (Sandbox Code Playgroud)