为了获得我的帐户,我需要登录一个外部spring应用程序。为什么需要它并不重要,但是为了对API进行/ login调用,我需要在UserDetailsServiceMethod中获取密码。这是我的安全设置:
//https://auth0.com/blog/implementing-jwt-authentication-on-spring-boot/
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
private UserDetailsService userDetailsService;
private BCryptPasswordEncoder bCryptPasswordEncoder;
//Constructor gets authLogic for external authentication
@Autowired
public WebSecurity(@Qualifier("authLogic") UserDetailsService userDetailsService){
this.userDetailsService = userDetailsService;
this.bCryptPasswordEncoder = new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.authorizeRequests()
.antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources", "/configuration/security", "/swagger-ui.html", "/webjars/**", "/swagger-resources/configuration/ui", "/swagger-resources/configuration/security").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.addFilter(new JwtAuthorizationFilter(authenticationManager()))
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList(BANK_API, INVENTORY_API, MARKET_API)); //TODO: is dit correct??
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "PATCH"));
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.setExposedHeaders(Arrays.asList("X-Auth-Token","Authorization","Access-Control-Allow-Origin","Access-Control-Allow-Credentials"));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
我的UserDetailsServiceMethod实现:
@Service
public class AuthLogic implements UserDetailsService {
private HttpServletRequest request;
private IAccountRepository accountRepository;
private RestCallLogic restCall;
@Autowired
public AuthLogic(HttpServletRequest request, IAccountRepository accountRepository, RestCallLogic restCall){
this.request = request;
this.accountRepository = accountRepository;
this.restCall = restCall;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//get password
//make restcall to external login
}
}
有没有一种方法可以在使用Spring Security实现时获取密码。因为我可以轻松地创建自己的类并从那里进行登录,但是最好使用Spring安全性。登录名还会返回一个令牌,我可以将其重新分配给用户。也许我只是在想...
为了进行API调用,我需要编写一个自定义AuthenticationProvider:
@Component
public class JwtAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = authentication.getCredentials().toString();
UserDetails principal = new User(username, password, new ArrayList<>());
return new UsernamePasswordAuthenticationToken(principal, password, new ArrayList<>());
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
最佳答案
在后台,Spring Security在过滤器中解析用户的凭证(例如BasicAuthenticationFilter
,UsernamePasswordAuthenticationFilter
等-过滤器检索用户凭证),如果这样的过滤器成功检索了用户的凭证,它将把这些凭证传递给AuthenticationProvider
来验证凭证和创建用户的详细信息(read more about AuthenticationProvider)。 AuthenticationProvider
可以通过多种方式验证凭据。AuthenticationProvider
的一种实现是DaoAuthenticationProvider
,它尝试通过UserDetailsService
中的用户名查找用户,如果找到,则从UserDetails
中为用户获取UserDetailsService
,然后检查用户提供的密码是否满足要求UserDetails
中的密码。
在您的情况下,您需要在UserDetailsService
中而不是在AuthenticationProvider
中提出这样的请求,因为它负责这种情况。
我的建议是从Spring安全性扩展AbstractUserDetailsAuthenticationProvider
类,并以抽象方法protected abstract UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException;
实现您的功能。
例如:
@Configuration
public class WebSecurityConf43547 extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(new AbstractUserDetailsAuthenticationProvider() {
@Override
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken) throws AuthenticationException {
//from docs: "[...]Generally a subclass will at least compare the
//Authentication.getCredentials() with a UserDetails.getPassword() [...]"
}
@Override
protected UserDetails retrieveUser(String s, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken) throws AuthenticationException {
usernamePasswordAuthenticationToken.getCredentials();
//your api here
}
});
}
}
更好的例子:看看
DaoAuthenticationProvider
如何在Spring安全性中扩展AbstractUserDetailsAuthenticationProvider
。