gpt4 book ai didi

java - 使用 CustomAuthenticationProvider 和 CustomPasswordEncoder 的 Spring-Boot

转载 作者:行者123 更新时间:2023-12-02 10:07:16 25 4
gpt4 key购买 nike

我不清楚如何将 CustomPasswordEncoder 粘合到 Spring Boot 的身份验证过程中。我在配置中定义 Spring Boot 应该将我的 CustomAuthenticationProvider 与我的 UserDetailsS​​ervice 和我的 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 的适配器。并使用它。我假设 UserDetailsS​​erviceImpl 正是这样做的。如果没有,您可以使用类似下面的代码。

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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com