我使用的是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
?
签出delegatingpasswordencoder:https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/crypto/password/delegatingpasswordencoder.html
它允许基于密码值中的前缀来确定使用哪个其他PasswordEncoder。