【问题标题】:SPRING: Add custom user details to spring security userSPRING:向 Spring Security 用户添加自定义用户详细信息
【发布时间】:2017-06-05 19:50:03
【问题描述】:

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

我阅读了很多关于自定义用户类和自定义服务的信息,但我无法真正找到解决我的问题的有效解决方案...

任何帮助都会很棒!

【问题讨论】:

    标签: java spring spring-mvc spring-security


    【解决方案1】:

    创建实现UserDetails 接口的类。

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

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

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

    【讨论】:

    • 嗯我不太明白...我用我的自定义字符串字段创建了一个用户类。生成了一堆方法,例如@Override public String getPassword() { // TODO Auto-generated method stub return null; } 然后我如何使用“用户”类进行弹簧安全性?还是自动工作?我认为示例代码会有很大帮助:/
    【解决方案2】:

    就像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 实现的示例: custom UserDetails

    【讨论】:

    • 如何使用 UserDao 类中设置的权限设置 Hibernate?
    【解决方案3】:

    我曾通过以下方式处理此问题。

    AccountDetailsS​​ervice.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

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

    【讨论】:

    • 嗨,我的 User 类有诸如 confirmPassword、createdAt、fullName 之类的字段。我是否必须将所有这些字段添加到我的 CustomUserDetails 类中?
    • @AbubakarIbrahim 你是对的。您需要在实现 UserDetails 接口(spring-security-core)的 CustomUserDetails 中添加那些
    【解决方案4】:

    如果要将角色发送为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;
    
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2012-05-23
      • 2021-09-09
      • 2017-12-11
      • 2013-12-13
      • 2011-06-24
      • 2012-07-20
      • 2013-07-23
      • 2019-01-01
      • 1970-01-01
      相关资源
      最近更新 更多