spring-security 使用用户/密码的Spring安全性

kg7wmglp  于 2022-11-11  发布在  Spring
关注(0)|答案(3)|浏览(205)

因此,我遵循了一些关于用户名和密码的Spring安全指南,但大多数指南显示使用“InMemoryUserDetailsManager”,他们说不应在生产中使用:

@Bean
public InMemoryUserDetailsManager userDetailsManager(){
    UserDetails admin = User.withDefaultPasswordEncoder()
            .username("ADMIN")
            .password("123")
            .roles("ADMIN").build();

    return new InMemoryUserDetailsManager(admin);
}

我的问题是,应该如何设置这个的生产级版本?它只是不使用默认的密码编码器,因为它被弃用了,还是我应该使用一种完全不同的方法来添加和存储用户?

l2osamch

l2osamch1#

您应该实现jdbc身份验证DaoAuthenticationProvider。 checkout https://www.baeldung.com/spring-security-jdbc-authentication
您的用户详细信息必须存储在永久存储中,而不是临时存储中。此外,密码必须加密,以避免危及安全性。因此,使用永久存储,您可以获取备份或数据,并从中运行查询。

n53p2ov0

n53p2ov02#

您可以实现自定义用户详细信息服务,而不使用默认服务。

@Service
public class CustomUserDetailsServiceImpl implements UserDetailsService {

    private final UserRepository userRepository;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    public CustomUserDetailsServiceImpl(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);

        if(user == null) {
            throw ApiExceptionFactory.getApiException(ApiExceptionType.NOT_FOUND, "user");
        }

        return new org.springframework.security.core.userdetails.User(
                user.getUsername(),
                user.getPassword(),
                user.getEnabled(),
                true,
                true,
                true,
                getAuthorities(user));
    }

    public Boolean isTokenValid(String token) {
        try {
            Jws<Claims> claimsJws = Jwts.parser().setSigningKey(SECRET.getBytes()).parseClaimsJws(token);
            return true;
        } catch (SignatureException | MalformedJwtException | UnsupportedJwtException | IllegalArgumentException ex) {
            throw ApiExceptionFactory.getApiException(ApiExceptionType.LOGIN_FAILURE, "invalid credentials");
        } catch (ExpiredJwtException ex) {
            throw ApiExceptionFactory.getApiException(ApiExceptionType.LOGIN_FAILURE, "token expired");
        }
    }

    @Transactional
    public Boolean save(User user){
        if(StringUtils.isEmpty(user.getUsername())) {
            throw ApiExceptionFactory.getApiException(ApiExceptionType.BAD_REQUEST, "username");
        }

        if(StringUtils.isEmpty(user.getPassword())) {
            throw ApiExceptionFactory.getApiException(ApiExceptionType.BAD_REQUEST, "password");
        }

        if(StringUtils.isEmpty(user.getEmail())) {
            throw ApiExceptionFactory.getApiException(ApiExceptionType.BAD_REQUEST, "email");
        }

        User registeredUser = new User();
        registeredUser.setUsername(user.getUsername());
        registeredUser.setPassword(passwordEncoder.encode(user.getPassword()));
        registeredUser.setEmail(user.getEmail());
        registeredUser.setEnabled(true);
        registeredUser.setRoles(user.getRoles());

        User savedUser = userRepository.save(registeredUser);

        Inventory userInventory = inventoryService.saveInventoryForUser(savedUser.getUsername());

        return userInventory != null;
    }

    private Set<GrantedAuthority> getAuthorities(User user){
        Set<GrantedAuthority> authorities = new HashSet<>();
        for(Role role : user.getRoles()) {
            GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(role.getName().getRole());
            authorities.add(grantedAuthority);
        }
        return authorities;
    }
}

您可以将用户详细信息保存到存储库中。

@Repository
public interface UserRepository extends BaseRepository<User> {

    User findByUsername(String username);

    Boolean existsByUsername(String username);

    Boolean existsByEmail(String email);

}

最后,使用密码编码器将用户详细信息添加到身份验证管理器中。

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserRepository userRepository;

    @Override
    public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder.userDetailsService(userDetailsServiceBean()).passwordEncoder(passwordEncoder());
    }

    @Override
    public UserDetailsService userDetailsServiceBean() {
        return new CustomUserDetailsServiceImpl(userRepository);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

更多详情请查看我的github repository

qxsslcnc

qxsslcnc3#

Hello Please Code编码如下

@Bean
public InMemoryUserDetailsManager createUserDetailsManager() {

    UserDetails userDetails1 = createNewUser("username1", "dummy");
    UserDetails userDetails2 = createNewUser("username2", "dummydummy");

    return new InMemoryUserDetailsManager(userDetails1, userDetails2);
}

private UserDetails createNewUser(String username, String password) {
    Function<String, String> passwordEncoder
    = input -> passwordEncoder().encode(input);

    UserDetails userDetails = User.builder()
                                .passwordEncoder(passwordEncoder)
                                .username(username)
                                .password(password)
                                .roles("USER","ADMIN")
                                .build();
    return userDetails;
}

希望对你有帮助

相关问题