- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我不清楚如何将 CustomPasswordEncoder 粘合到 Spring Boot 的身份验证过程中。我在配置中定义 Spring Boot 应该将我的 CustomAuthenticationProvider 与我的 UserDetailsService 和我的 CustomPasswordEncoder 结合使用
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Autowired
private CustomAuthenticationProvider customAuthenticationProvider;
@Autowired
protected void configureGlobal(AuthenticationManagerBuilder builder) throws Exception {
builder.authenticationProvider(customAuthenticationProvider)
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder(){
PasswordEncoder encoder = new CustomPasswordEncoder();
return encoder;
}
}
我的 CustomPasswordEncoder 将编码为 md5 值(我知道它不安全,但它是旧数据库)
@Component
public class CustomPasswordEncoder implements PasswordEncoder{
@Override
public String encode(CharSequence rawPassword) {
return DigestUtils.md5DigestAsHex(rawPassword.toString().getBytes());
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return rawPassword.toString().equals(encodedPassword);
}
}
将在 CustomAuthtenticationProvider 中完成身份验证检查。传递的密码将使用passwordEncoder.encode()进行编码。将从数据库中获取用户,然后我再次使用passwordEncoder进行匹配。如果匹配成功则生成认证对象。
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Autowired
private UserServiceImpl userService;
@Autowired
private CustomPasswordEncoder passwordEncoder;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
System.out.println("authentication = [" + authentication + "]");
String name = authentication.getName();
Object credentials = authentication.getCredentials();
String password = credentials.toString();
//why is this necessary isnt it called automatically?
String passwordEncoded = passwordEncoder.encode((CharSequence) credentials);
Optional<UserEntity> userOptional = userService.findByUsername(name);
if (userOptional.isPresent() && passwordEncoder.matches(passwordEncoded, userOptional.get().getPassword())) {
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
grantedAuthorities.add(new SimpleGrantedAuthority(userOptional.get().getRoles().toString()));
Authentication auth = new
UsernamePasswordAuthenticationToken(name, password, grantedAuthorities);
return auth;
}
else{
throw new BadCredentialsException("Authentication failed for " + name);
}
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
这是正确的方法吗?我认为 CustomPasswordEncoder 将“自动”使用,或者只有当您使用提供的身份验证提供程序之一(如 jdbcAuthenticationProvider)时才会出现这种情况。也许有人可以解释身份验证过程的事件顺序。我在网上做了一些研究,但仍然无法详细理解这一点。
最佳答案
首先,正如您从 matches
中看到的那样方法它使用编码密码验证原始密码(因此由用户输入)。因此,编码的代码属于 matches
方法,而不是您现在的代码。
public class CustomPasswordEncoder implements PasswordEncoder{
@Override
public String encode(CharSequence rawPassword) {
return DigestUtils.md5DigestAsHex(rawPassword.toString().getBytes());
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
String rawEncoded = encode(rawPassword);
return Objects.equals(rawEncoded, encodedPassword);
}
}
现在您可以从代码中删除任何编码行/步骤。
但是,您实际上并不需要自定义 AuthenticationProvider
,因为通常只有在添加其他身份验证机制(例如 LDAP 或 OAuth)时才需要它。
您需要的是一个将 UserService
适配器连接到 UserDetailsService
的适配器。并使用它。我假设 UserDetailsServiceImpl 正是这样做的。如果没有,您可以使用类似下面的代码。
public class UserDetailsServiceImpl implements UserDetailsService {
private final UserService delegate;
public UserDetailsServiceAdapter(UserService delegate) {
this.delegate=delegate;
}
public UserDetails loadUserByUsername(String username) {
reutrn userService.findByUsername(name)
.map(this::toUserDetails).orElseThrow(() -> new UsernameNotFoundException("Unknown user " + username);
}
private UserDetails toUserDetails(User user) {
Set<GrantedAuthority> authorities = new HashSet<>();
user.getRoles().forEach(r -> authorities.add(new SimpleGrantedAuthority(r));
return new UserDetails(user.getUsername(), user.getPassword(), authorities);
}
}
现在您可以在配置中使用您的 PasswordEncoder
和此适配器,并且不需要自定义 AuthenticationProvider
。
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Autowired
protected void configureGlobal(AuthenticationManagerBuilder builder) throws Exception {
builder.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder(){
PasswordEncoder encoder = new CustomPasswordEncoder();
return encoder;
}
}
关于java - 使用 CustomAuthenticationProvider 和 CustomPasswordEncoder 的 Spring-Boot,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55262046/
我不清楚如何将 CustomPasswordEncoder 粘合到 Spring Boot 的身份验证过程中。我在配置中定义 Spring Boot 应该将我的 CustomAuthenticatio
我是一名优秀的程序员,十分优秀!