简体   繁体   English

Spring 用户/密码安全

[英]Spring security with user/password

So I followed some guides on spring security with usernames and passwords, however most of them show using "InMemoryUserDetailsManager" which they say should not be used in production:因此,我遵循了一些关于 spring 安全性的用户名和密码指南,但其中大多数显示使用“InMemoryUserDetailsManager”,他们说不应在生产中使用:

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

    return new InMemoryUserDetailsManager(admin);
}

My questions, so how should a production level version of this be setup?我的问题是,应该如何设置生产级别的版本? Is it just not using the default password encoder because it is deprecated or should I use an entirely different method of adding and storing users?它只是不使用默认密码编码器,因为它已被弃用,还是我应该使用完全不同的方法来添加和存储用户?

You should implement jdbc authentication DaoAuthenticationProvider .您应该实施 jdbc 身份验证DaoAuthenticationProvider Checkout https://www.baeldung.com/spring-security-jdbc-authentication .结账https://www.baeldung.com/spring-security-jdbc-authentication

Your user details must be stored in permanent storage, not temporary storage.您的用户详细信息必须存储在永久存储中,而不是临时存储中。 Also, passwords must be encrypted to avoid compromising security.此外,必须对密码进行加密以避免危及安全性。 So using permanent storage you can take backup or data and run queries out of it.因此,使用永久存储,您可以获取备份或数据并从中运行查询。

You can implement custom user details service instead of using default.您可以实现自定义用户详细信息服务,而不是使用默认服务。

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

You can save user details into your repository.您可以将用户详细信息保存到您的存储库中。

@Repository
public interface UserRepository extends BaseRepository<User> {

    User findByUsername(String username);

    Boolean existsByUsername(String username);

    Boolean existsByEmail(String email);

}

Finally add your user details into authentication manager with password encoder.最后将您的用户详细信息添加到带有密码编码器的身份验证管理器中。

@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();
    }
}

For more details check my github repository有关详细信息,请查看我的github 存储库

Hello Please Code as the following coding您好请编码如下编码

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

Hope it help you希望对你有帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM