[英]AuthenticationPrincipal returns empty UserDetails object
I'm trying to secure my api endpoints by spring security + jwt token.我正在尝试通过 spring 安全性 + jwt 令牌来保护我的 api 端点。 So far, the token generator and veficator work well.到目前为止,令牌生成器和验证器运行良好。 The problem arises when i use AuthenthicationPrincipal
in method argument to get current UserDetails
.当我在方法参数中使用AuthenthicationPrincipal
来获取当前的UserDetails
时,就会出现问题。 I have my class Account
implement UserDetails
, and my TokenAuthenticationProvider
provide the necessary Account
based on header bearer's token.我的 class Account
实现了UserDetails
,我的TokenAuthenticationProvider
提供了基于 header 持票人令牌的必要Account
。
Partial code of configuration and controller:部分配置代码和controller:
@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();
}
}
Tracing in debug mode shows that the TokenAuthenticationProvider
has retrieved correctly the Account
.在调试模式下跟踪显示TokenAuthenticationProvider
已正确检索到Account
。 Only when called in the controller, an empty Account
is returned ( null
attributes)只有在controller中调用时,才会返回一个空Account
( null
属性)
@RepositoryRestController
@RequiredArgsConstructor
@BasePathAwareController
@RequestMapping(path = "account")
class AccountController {
@GetMapping("current")
@ResponseBody
Account getCurrent(@AuthenticationPrincipal Account account) {
return account;
}
}
The filter chain is correct though:过滤器链是正确的:
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
]
I looked into some tutorials and questions but could not deduce any suitable answer.我查看了一些教程和问题,但无法推断出任何合适的答案。
https://octoperf.com/blog/2018/03/08/securing-rest-api-spring-security/ (which inspires my current implementation) https://octoperf.com/blog/2018/03/08/securing-rest-api-spring-security/ (这激发了我当前的实现)
https://svlada.com/jwt-token-authentication-with-spring-boot/#jwt-authentication https://svlada.com/jwt-token-authentication-with-spring-boot/#jwt-authentication
@AuthenticationPrincipal return empty User (this one use DelegatingFlashMessagesConfiguration
which does not exist in my case) @AuthenticationPrincipal 返回空用户(这个使用DelegatingFlashMessagesConfiguration
在我的情况下不存在)
Does it have anything to do with the order of configuration or filters?它与配置或过滤器的顺序有关吗?
For @AuthenticationPrincipal to work I need to override addArgumentResolvers要使 @AuthenticationPrincipal 起作用,我需要覆盖 addArgumentResolvers
@Configuration
public class WevMvcConfiguration extends WebMvcConfigurationSupport {
@Override
protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(new AuthenticationPrincipalArgumentResolver());
}
}
new AuthenticationPrincipalArgumentResolver()
use import org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver
new AuthenticationPrincipalArgumentResolver()
使用导入org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver
Custom class implement UserDetails自定义 class 实现 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
}
Now working really well.现在工作得很好。
@GetMapping(value="/me")
public User getMe(@AuthenticationPrincipal UserPrincipal currentUser){
logger.debug("name: "+currentUser.getUsername());
return this.userService.findByUsername(currentUser.getUsername());
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.