我的应用程序有基于 spring 3 xml 的配置。 我正在从 Postman 调用 REST API(不是基于表单的登录),并在授权标头中使用用户名密码。 对于身份验证,我创建了实现 AuthenticationProvider 的身份验证提供程序。
<security:authentication-manager>
<security:authentication-provider ref="restAuthentication"/>
</security:authentication-manager>
问题是如何在自定义身份验证提供程序中获取凭据? AuthenticationProvider 不会在重写身份验证方法中提供带有标头的身份验证请求。
或者,我尝试扩展 BasicAuthenticationEntryPoint,但在 afterPropertiesSet() 方法之后运行应用程序时出现错误。
@Override
public void afterPropertiesSet() throws Exception {
setRealmName("Spring");
super.afterPropertiesSet();
}
创建名称为“org.springframework.security.authenticationManager”的bean时出错:通过构造函数参数0表达的依赖关系不满足:无法将类型[java.util.ArrayList]的参数值转换为所需类型[java.util.List]:失败将“java.util.ArrayList”类型的值转换为所需类型“java.util.List”。
请建议这两种方式中哪一种合适,以及如何解决冲突。
从请求中检索凭据并将其发送到
AuthenticationManager
的责任通常来自 Filter
,请参阅 BasicAuthenticationFilter
。
也就是说,您可能需要一个过滤器或控制器端点,将
HttpServletRequest
转换为 Authentication
对象,并将该对象传递给自动装配的 AuthenticationManager
。
这是我的解决方案:
安全配置
@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
private BasicAuthManager basicAuthManager;
@Autowired
public SecurityConfiguration(BasicAuthManager basicAuthManager) {
this.basicAuthManager = basicAuthManager;
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(requests -> requests
.anyRequest().authenticated())
.authenticationManager(basicAuthManager)
.httpBasic(withDefaults())
.build();
}
}
基本身份验证管理器
@Service
public class BasicAuthManager implements AuthenticationManager {
private final UserDetailsService userDetailsService;
private final PasswordEncoder passwordEncoder;
@Autowired
public BasicAuthManager(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
this.userDetailsService = userDetailsService;
this.passwordEncoder = passwordEncoder;
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
final String username = authentication.getName();
final String password = authentication.getCredentials().toString();
UserDetails user;
try {
user = userDetailsService.loadUserByUsername(username);
} catch (UsernameNotFoundException ex) {
throw new BadCredentialsException("User does not exists");
}
if (StringUtils.isBlank(password) || !passwordEncoder.matches(password, user.getPassword())) {
throw new BadCredentialsException("Password is wrong");
}
return new UsernamePasswordAuthenticationToken(username, null, user.getAuthorities());
}
}
安全Beans
@Configuration
public class SecurityBeans {
@Value("${my.security.username}")
private String username;
@Value("${my.security.password}")
private String password;
@Value("${my.security.userRole}")
private String userRole;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public UserDetailsService userDetailsService() {
UserDetails userDetails = User
.withUsername(username)
.password(passwordEncoder().encode(password))
.roles(userRole)
.build();
return new InMemoryUserDetailsManager(userDetails);
}
}