我目前正在开发Spring MVC应用程序,我需要在登录时向我的Spring Security登录用户添加一个自定义字段(我插入用户名,密码,自定义值)。当用户登录时,此值需要在任何地方可用(例如,通过 pricipal.getValue)。
我阅读了很多关于自定义用户类和自定义服务的信息,但无法真正找到解决我的问题的工作解决方案......
任何帮助都会很棒!
就像 Avinash 说的,你可以让你的User
类实现UserDetails
,你也可以实现UserDetailsService
和重写相应的方法来返回自定义User
对象:
@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {
//get user from the database, via Hibernate
@Autowired
private UserDao userDao;
@Transactional(readOnly=true)
@Override
public UserDetails loadUserByUsername(final String username)
throws UsernameNotFoundException {
//CUSTOM USER HERE vvv
User user = userDao.findByUserName(username);
List<GrantedAuthority> authorities =
buildUserAuthority(user.getUserRole());
//if you're implementing UserDetails you wouldn't need to call this method and instead return the User as it is
//return buildUserForAuthentication(user, authorities);
return user;
}
// Converts user to spring.springframework.security.core.userdetails.User
private User buildUserForAuthentication(user,
List<GrantedAuthority> authorities) {
return new User(user.getUsername(), user.getPassword(),
user.isEnabled(), true, true, true, authorities);
}
private List<GrantedAuthority> buildUserAuthority(Set<UserRole> userRoles) {
Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();
// add user's authorities
for (UserRole userRole : userRoles) {
setAuths.add(new SimpleGrantedAuthority(userRole.getRole()));
}
List<GrantedAuthority> Result = new ArrayList<GrantedAuthority>(setAuths);
return Result;
}
}
您只需使用自定义UserdetailsService
配置WebConfigurerAdapter
:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("userDetailsService")
UserDetailsService userDetailsService;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//authorization logic here ...
}
@Bean
public PasswordEncoder passwordEncoder(){
// return preferred PasswordEncoder ...//
}
}
下面是自定义UserDetails
实现的示例:自定义用户详细信息
创建实现UserDetails
接口的类。
public class User implements UserDetails {
// Your user properties
// implement methods
}
然后,一旦通过身份验证,您就可以像这样在项目中的任何位置访问此对象。
User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
我通过以下方式进行了研究。
帐户详细信息服务.java
@Service
public class AccountDetailsService implements UserDetailsService {
@Autowired
AccountRepository accountRepository;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException, JSONException {
return loadUser(s);
}
public UserDetails loadUserByUsernameWithoutCredentials(String s) throws UsernameNotFoundException, JSONException {
CustomUserDetails customUserDetails=loadUser(s);
if (customUserDetails != null){
customUserDetails.eraseCredentials();
}
return customUserDetails;
}
private CustomUserDetails loadUser(String s) throws UsernameNotFoundException, JSONException {
Account userAccount = accountDbRepository.getAccountByUserName(s);
if (userAccount==null){
return null;
}
Collection<GrantedAuthority> grantedAuthoritySet = new HashSet<>();
for (int i=0; i<userAccount.getRoles().size();i++)
{
JSONObject jsonObject = new JSONObject(userAccount.getRoles().get(i));
String role = jsonObject.getString("role");
gas.add(new SimpleGrantedAuthority(role));
}
return new CustomUserDetails(userAccount.getEmail(),userAccount.getDisplayName(),userAccount.getUserName(),userAccount.getPassword(),userAccount.getEnabled(),gas);
}
}
自定义用户详细信息.java
public class CustomUserDetails implements UserDetails {
private Collection<? extends GrantedAuthority> authorities;
private String email;
private String displayName;
private String password;
private String username;
private Boolean enabled;
private Boolean accountNonExpired;
private Boolean accountNonLocked;
private boolean credentialsNonExpired;
public CustomUserDetails(String email, String displayName, String username, String password, Boolean enabled, Collection<? extends GrantedAuthority> authorities) {
this.email = email;
this.displayName = displayName;
this.enabled=enabled;
this.username=username;
this.password=password;
this.accountNonExpired=true;
this.accountNonLocked=true;
this.credentialsNonExpired=true;
this.authorities=authorities;
}
public CustomUserDetails(String email, String displayName, String password, String username, Boolean enabled, Boolean accountNonExpired, Boolean accountNonLocked, boolean credentialsNonExpired, Collection<? extends GrantedAuthority> authorities) {
this.authorities = authorities;
this.email = email;
this.displayName = displayName;
this.password = password;
this.username = username;
this.enabled = enabled;
this.accountNonExpired = accountNonExpired;
this.accountNonLocked = accountNonLocked;
this.credentialsNonExpired = credentialsNonExpired;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
@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 accountNonExpired;
}
@Override
public boolean isAccountNonLocked() {
return accountNonLocked;
}
@Override
public boolean isCredentialsNonExpired() {
return credentialsNonExpired;
}
@Override
public boolean isEnabled() {
return enabled;
}
public void eraseCredentials(){
this.password=null;
}
}
如果要将角色作为ADMIN/USER
发送角色,请不要直接userRole.getRole()
,而是将其编写为"ROLE_" + userRole.getRole()
。这样您就可以无错误地运行代码。
例:
@Service("listUserDetailsService")
public class ListUserDetailsService implements UserDetailsService {
@Transactional(readOnly = true)
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException{
User user = userRepo.findByEmail(email);
if (user == null) {
throw new UsernameNotFoundException("Invalid User");
} else {
Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
for (Role role : user.getRoles()){
grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_"+role.getName()));
}
return new org
.springframework
.security
.core
.userdetails
.User(user.getEmail(), user.getPassword(), grantedAuthorities);
}
}
private final UserRepo userRepo;
public ListUserDetailsService(UserRepo userRepo) {
this.userRepo = userRepo;
}
}