[英]Principal stays string albeit using a custom user details class in Spring security
I have a custom UserDetailsService
as follows: 我有一个自定义UserDetailsService
如下:
@Service
public class AuthenticatedUserService implements UserDetailsService {
private final UserRepository userRepository;
@Autowired
public AuthenticatedUserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String username) {
UserCredentials userCredentials = userRepository.findByUsername(username);
if (userCredentials == null) {
throw new UsernameNotFoundException("The user " + username + " does not exist");
}
return new AuthenticatedPrincipal(userCredentials);
}
}
My AuthenticatedPrincipal
looks like this: 我的AuthenticatedPrincipal
看起来像这样:
public class AuthenticatedPrincipal implements UserDetails {
private UserCredentials userCredentials;
public AuthenticatedPrincipal() {
}
public AuthenticatedPrincipal(UserCredentials userCredentials) {
this.userCredentials = userCredentials;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> authorities = new ArrayList<>();
...
return authorities;
}
@Override
public String getPassword() {
return userCredentials.getPassword();
}
@Override
public String getUsername() {
return userCredentials.getUsername();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
I'm using my service this way: 我这样使用我的服务:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Qualifier("authenticatedUserService")
@Autowired
private UserDetailsService userDetailsService;
@Autowired
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// auth.ldapAuthentication()
auth.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder);
}
...
}
And everything works. 一切正常。 I can login just fine. 我可以登录就好了。 BUT I never get my custom principal. 但我从来没有得到我的定制校长。 In every place a just get a plain string containing the user name. 在每个地方,只需获取一个包含用户名的普通字符串。 For example, I want to implement a custom SecurityExpressionRoot
. 例如,我想实现自定义SecurityExpressionRoot
。
public class CustomMethodSecurityExpressionRoot
extends SecurityExpressionRoot implements MethodSecurityExpressionOperations {
public CustomMethodSecurityExpressionRoot(Authentication authentication) {
super(authentication);
}
public boolean isMember(Long OrganizationId) {
// Throws an exception, because principal is just a string
AuthenticatedPrincipal user = (AuthenticatedPrincipal) this.getPrincipal();
return false;
}
The same happens when I try to insert it into one of my controllers. 当我尝试将其插入我的一个控制器时也会发生同样的情况。
public ResponseEntity listMessages(@AuthenticationPrincipal Principal principal) {
I don't know what to do and try any more. 我不知道该怎么办,再试一次。 I don't see any difference from what I've done and this tutorial , for example. 例如,我没有看到与我所做的和本教程有任何区别。
尝试将主体类型从“Principal”更改为控制器中的“AuthenticatedPrincipal”。
Okay, I've managed to track down and solve my issue. 好的,我已经设法找到并解决了我的问题。 I am using JWT and was using a custom filter, which sets the authentication. 我正在使用JWT并使用自定义过滤器来设置身份验证。 Instead of returning a proper Authentication
object, I had been using the default UsernamePasswordAuthenticationToken
. 我没有返回正确的Authentication
对象,而是使用了默认的UsernamePasswordAuthenticationToken
。 To solve this, I went ahead and created my own token class: 为了解决这个问题,我继续创建了自己的令牌类:
public class TokenBasedAuthentication extends AbstractAuthenticationToken {
private final UserDetails principal;
public TokenBasedAuthentication(AuthenticatedPrincipal principal) {
super(principal.getAuthorities());
this.principal = principal;
}
@Override
public boolean isAuthenticated() {
return true;
}
@Override
public UserDetails getPrincipal() {
return principal;
}
}
Then, in my filter, I went ahead and created a proper authentication object: 然后,在我的过滤器中,我继续创建了一个合适的身份验证对象:
AuthenticatedPrincipal userDetails = (AuthenticatedPrincipal) userDetailsService.loadUserByUsername(username);
TokenBasedAuthentication authentication = new TokenBasedAuthentication(userDetails);
SecurityContextHolder.getContext().setAuthentication(authentication);
Now I'm getting the right principal as well. 现在我也得到了正确的校长。 Actually should have figured that out sooner, but all well, I guess. 实际上应该早点把它想出来,但是一切都好,我想。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.