我的目标是从Principal
中删除Password。
注意:默认情况下,Spring Security没有在Principal中存储Password。我覆盖UserDetailsService
添加更多的信息,如name
,id
,channelIds
。但是,我的实现将密码存储在Principal
中,我认为这是不好的。
您可以通过创建get端点来获取主体:
@RestController
public class UserDetailsController {
@GetMapping("/userdetails")
public Principal getUserDetails(Principal user) {
return user;
}
}
这是我的实现,以获得更多的信息,如name
,id
,channelIds
等。
@RestController
public class UserDetailsController {
// TODO: hide password.
@GetMapping("/userdetails")
public MyUserDetails getUserDetails(@CurrentSecurityContext(expression = "authentication.principal") Object user) {
return (MyUserDetails) user;
}
}
我的预期结果是密码为空。
我的实际结果是密码不为空。例如,数据库中的密码是加密的ewaejovra
,则存储在Principal中的密码将是ewaejovra
。
这是我的实现
WebSecurityConfig.java
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final UserDetailsService userDetailsService;
public WebSecurityConfig(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
...
}
MyUserDetailsService.java
@Service
public class MyUserDetailsService implements UserDetailsService {
private final UserMapper userMapper;
public MyUserDetailsService(UserMapper userMapper) {
this.userMapper = userMapper;
}
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
Optional<UserModel> user = userMapper.getUser(s);
user.orElseThrow(() -> new UsernameNotFoundException("Username Not Found: " + s)); // TODO: who receives the Exception?
return user.map(MyUserDetails::new).get();
}
}
MyUserDetails.java
public class MyUserDetails implements UserDetails {
private final String userId;
private final String username;
private String password;
private final boolean active;
private final Set<GrantedAuthority> authorities;
public MyUserDetails(UserModel user) {
this.userId = user.getId();
this.username = user.getUser();
this.password = user.getPassword();
this.active = user.getActive();
this.authorities = Set.of(new SimpleGrantedAuthority("ROLE_USER"));
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return active;
}
public String getUserId() {
return userId;
}
}
您不能从原则对象中删除密码,您可以避免在请求时发送密码,但是一旦发送,它将被原则拾取,以便在Spring Security中使用它。
这真的取决于你做安全的方式,例如,如果用户必须通过他的信用(username
+password
)在每个请求访问安全的资源,你将最终拥有密码总是在原则上是有意义的,在结束密码只是一些字符串需要安全。
另一方面,如果你使用一些JWT访问令牌,一旦消费者执行成功登录,然后他会与你的服务器交换它来访问安全的资源,在这种安全风格下,你会在principle
对象中看到password
一次,在用户第一次登录时,但是在那之后,你只会在主要对象中看到访问令牌查看https://dzone.com/articles/spring-boot-security-json-web-tokenjwt-hello-world获取更多信息