Java SPRING:将自定义用户详细信息添加到 spring 安全用户

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41770156/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 23:40:09  来源:igfitidea点击:

SPRING: Add custom user details to spring security user

javaspringspring-mvcspring-security

提问by counter1602

I'm currently working on a Spring MVC application and I need to add a custom field to my Spring Security log-in user right when I log in (I insert username, password, custom value). This value needs to be available on everywhere when the user is logged in (e.g. via pricipal.getValue).

我目前正在开发一个 Spring MVC 应用程序,我需要在登录时为我的 Spring Security 登录用户添加一个自定义字段(我插入用户名、密码、自定义值)。当用户登录(例如通过 pricipal.getValue)时,该值需要在任何地方都可用。

I read a lot about custom user classes and custom services, but can't really find a working solution for my problem...

我阅读了很多关于自定义用户类和自定义服务的内容,但无法真正为我的问题找到可行的解决方案......

Any help would be great!

任何帮助都会很棒!

采纳答案by Daniel Arechiga

Just like Avinash said, you can make your Userclass implement UserDetailsand you can also implement UserDetailsServiceand override corresponding methods to return the custom Userobject:

就像 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;
    }

}

And you just configure your WebConfigurerAdapterusing the custom UserdetailsService:

您只需WebConfigurerAdapter使用 custom 进行配置UserdetailsService

@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 ...//
    }


}

Here, a sample of a custom UserDetailsimplementation: custom UserDetails

这里是一个自定义UserDetails实现的示例: custom UserDetails

回答by Avinash

Create your class implementing UserDetailsinterface.

创建您的类实现UserDetails接口。

public class User implements UserDetails {
    // Your user properties
    // implement methods
}

And then, once authenticated, you can access this object anywhere in the project like this.

然后,一旦通过身份验证,您就可以像这样在项目中的任何地方访问此对象。

User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();

回答by viveknaskar

I had worked on this in the following way.

我通过以下方式处理过这个问题。

AccountDetailsService.java

帐户详细信息服务.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);

    }

}

CustomUserDetails.java

自定义用户详细信息.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;
    }

}

回答by Sriraj

Don't directly wite userRole.getRole()directly if you want to send the role as ADMIN/USERinstead write it as "ROLE_" + userRole.getRole(). So that you can get the error-free run of your code.

userRole.getRole()如果要发送角色,请不要直接直接 wite ,ADMIN/USER而是将其写为"ROLE_" + userRole.getRole(). 这样您就可以获得无错误的代码运行。

Example:

例子:

@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;

    }

}