提问者:小点点

spring Security AuthenticationManager设置PasswordEncoder


我使用的是springboot 2.3.1.与Java 14一起发布。

我有spring安全工作正确,即它可以接收用户名&; 密码并返回一个jwt令牌。 根据令牌成功验证各种api调用。

这是我的WebSecurityConfigurerAdapter

SecurityConfig.java

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    @Qualifier("datasource1")
    private DataSource dataSource;

    @Autowired
    private JwtRequestFilter jwtRequestFilter;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication().dataSource(dataSource)
        .usersByUsernameQuery("SELECT username, password, (NOT disabled) as enabled FROM members "+
                "WHERE username = ?")
        .authoritiesByUsernameQuery("SELECT m.username, t.name as authority FROM members m " +
                "JOIN administrator a ON a.member_id = m.member_id " +
                "JOIN admin_type t ON t.admin_type_id = a.admin_type_id "+
                "WHERE m.username = ?");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // set up the jwt auth
        http.cors().disable();
        http.csrf().disable().authorizeRequests().antMatchers("/authenticate").permitAll()//.anyRequest().authenticated()
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                .and().exceptionHandling()
                .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // don't manage sessions, using jwt
        http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);

        // define the role mappings
        http.authorizeRequests()
                .antMatchers("/admin").hasAuthority("approver admin")
                .antMatchers("/approvals").hasAuthority("approver admin")
                //.antMatchers("/rest/*").hasAuthority("approver admin")
                .antMatchers("/hello").permitAll();

        // INSERT INTO admin_type (admin_type_id, name, description) VALUES ((SELECT MAX(admin_type_id) +1 FROM admin_type), 'approver admin', 'Able to alter approval requests');
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

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

我还有一个RESTful资源。 它接收包含用户名和原始密码的AuthenticationRequest

ApprovalsResource.java

@RequestMapping(value = "/authenticate", method = RequestMethod.POST)
public ResponseEntity<?> createAuthenticationToken(@RequestBody AuthenticationRequest authenticationRequest) throws Exception {
    try {
        authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(), authenticationRequest.getPassword())
        );
    } catch (BadCredentialsException e) {
        logger.info("Incorrect username or password for "+authenticationRequest.getUsername());
        throw new Exception("Incorrect username or password", e);
    }
    final UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername());
    final String jwt = jwtTokenUtil.generateToken(userDetails);
    final String username = jwtTokenUtil.extractUserName(jwt);
    logger.info("User just logged in: "+username);
    return ResponseEntity.ok(new AuthenticationResponse(jwt));
}

当收到原始(未加密)密码时,这一切都与NexctPasswordEncoder一起完美工作。 NexctPasswordEncoder加密要与数据库中加密的密码进行比较的密码。

问题

当我收到加密密码而不是原始密码时,我还需要满足这种情况。

解决方案

我需要让上面的代码与两个不同的passwordencoder一起工作。

理想情况下,在ApprovalsResource中,接收带有用户名和密码的请求,并调用以下内容:

authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(), authenticationRequest.getPassword())

我想设置相关的passwordencoder(一个加密密码,另一个不加密)。

问题

如何根据请求中的参数交换PassworDenCoder


共1个答案

匿名用户

签出delegatingpasswordencoder:https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/crypto/password/delegatingpasswordencoder.html

它允许基于密码值中的前缀来确定使用哪个其他PasswordEncoder。