authenticationprincipal返回空的userdetails对象

ql3eal8s  于 2021-07-26  发布在  Java
关注(0)|答案(1)|浏览(470)

我正试图通过springsecurity+jwt令牌来保护我的api端点。到目前为止,令牌生成器和验证程序运行良好。当我使用 AuthenthicationPrincipal 在方法参数中获取当前值 UserDetails . 我有我的课 Account 实施 UserDetails ,还有我的 TokenAuthenticationProvider 提供必要的 Account 基于报头持有者的令牌。
配置和控制器部分代码:

@Configuration
@EnableWebSecurity(debug = true)
@EnableGlobalMethodSecurity(prePostEnabled = true)
@RequiredArgsConstructor
class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Value("${spring.data.rest.basePath}")
    private String apiBasePath;
    private RequestMatcher protectedUrls;
    private RequestMatcher publicUrls;

    @NotNull
    private final TokenAuthenticationProvider provider;

    @PostConstruct
    private void postConstruct() {
        protectedUrls = new OrRequestMatcher(
                // Api
                new AntPathRequestMatcher(apiBasePath + "/**")
        );
        publicUrls = new NegatedRequestMatcher(protectedUrls);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .exceptionHandling()
                // when request a protected page without having authenticated
                .defaultAuthenticationEntryPointFor(forbiddenEntryPoint(),
                        protectedUrls)
                .and()
                // Authenticating with rest requests
                .authenticationProvider(provider)
                .addFilterBefore(restAuthenticationFilter(), // injecting TokenAuthenticationProvider here
                        AnonymousAuthenticationFilter.class)
                .authorizeRequests()
                .requestMatchers(protectedUrls)
                .authenticated()
                .and()
                // Disable server rendering for logging
                .formLogin().disable()
                .httpBasic().disable()
                .logout().disable();
    }
}

在调试模式下跟踪显示 TokenAuthenticationProvider 已正确检索 Account . 仅当在控制器中调用时,空 Account 被退回( null 属性)

@RepositoryRestController
@RequiredArgsConstructor
@BasePathAwareController
@RequestMapping(path = "account")
class AccountController {
    @GetMapping("current")
    @ResponseBody
    Account getCurrent(@AuthenticationPrincipal Account account) {
        return account;
    }
}

不过,过滤链是正确的:

servletPath:/api/account/current
pathInfo:null
headers: 
authorization: Bearer eyJhbGciOiJIUzI1NiIsInppcCI6IkdaSVAi...
user-agent: PostmanRuntime/7.19.0
accept: */*
cache-control: no-cache
postman-token: 73da9eb7-2ee1-43e8-9cd0-2658e4f32d1f
host: localhost:8090
accept-encoding: gzip, deflate
connection: keep-alive

Security filter chain: [
  WebAsyncManagerIntegrationFilter
  SecurityContextPersistenceFilter
  HeaderWriterFilter
  CsrfFilter
  RequestCacheAwareFilter
  SecurityContextHolderAwareRequestFilter
  TokenAuthenticationFilter
  AnonymousAuthenticationFilter
  SessionManagementFilter
  ExceptionTranslationFilter
  FilterSecurityInterceptor
]

我看了一些教程和问题,但无法推断出任何合适的答案。
https://octoperf.com/blog/2018/03/08/securing-rest-api-spring-security/ (这启发了我目前的实施)
https://svlada.com/jwt-token-authentication-with-spring-boot/#jwt-身份验证
@authenticationprincipal返回空用户(此用户使用 DelegatingFlashMessagesConfiguration 在我的案例中不存在)
它是否与配置或过滤器的顺序有关?

uqzxnwby

uqzxnwby1#

为了@authenticationprincipal工作,我需要重写addargumentresolvers

@Configuration
public class WevMvcConfiguration extends WebMvcConfigurationSupport {

    @Override
    protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(new AuthenticationPrincipalArgumentResolver());
    }    
}
``` `new AuthenticationPrincipalArgumentResolver()` 使用导入 `org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver` 自定义类实现userdetails

public class UserPrincipal implements UserDetails {

private static final long serialVersionUID = 1L;    
private ObjectId id;        
private String name;    
private String username;    
private String email;    
@JsonIgnore
private String password;    
//constructor, getter, etc    

}

现在工作得很好。

@GetMapping(value="/me")
public User getMe(@AuthenticationPrincipal UserPrincipal currentUser){
logger.debug("name: "+currentUser.getUsername());
return this.userService.findByUsername(currentUser.getUsername());
}

相关问题