在我们的项目中,如果用户使用承载令牌调用api,我们将使用oauth2身份验证。
如果用户使用基本身份验证调用api,则可以为基本身份验证添加第二个securityConfig。 但是我如何才能针对oauth2提供程序对这个basicAuth用户进行身份验证?
我尝试使用customAuthenticationProvider通过restTemplate获取访问令牌,这可行。
还有其他解决方法吗?
这是我的SecurityConfig:
@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
@Configuration
@EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Value("${security.oauth2.resource.id}")
private String resourceId;
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(resourceId);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/api/**").permitAll()
.antMatchers("/api/**").authenticated();
}
}
@Order(2)
@Configuration
protected static class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
private final RestTemplateBuilder restTemplateBuilder;
@Value("${oauth2.issuer}")
private String issuer;
@Autowired
public WebSecurityConfiguration(RestTemplateBuilder restTemplateBuilder) {
this.restTemplateBuilder = restTemplateBuilder;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.anonymous().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.requestMatcher(new BasicRequestMatcher())
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/api/**").permitAll()
.antMatchers("/api/**").authenticated()
.and()
.httpBasic();
}
private static class BasicRequestMatcher implements RequestMatcher {
@Override
public boolean matches(HttpServletRequest request) {
String auth = request.getHeader("Authorization");
return (auth != null && auth.startsWith("Basic"));
}
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(new OauthAuthenticationProvider(restTemplateBuilder, issuer));
}
}
}
这是CustomAuthenticationProvider
@Slf4j
public class OauthAuthenticationProvider implements AuthenticationProvider {
private final RestTemplateBuilder restTemplateBuilder;
private String issuer;
OauthAuthenticationProvider(RestTemplateBuilder restTemplateBuilder, String issuer) {
this.restTemplateBuilder = restTemplateBuilder;
this.issuer = issuer;
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> authorizationParameters = new LinkedMultiValueMap<>();
authorizationParameters.add("username", authentication.getPrincipal().toString());
authorizationParameters.add("password", authentication.getCredentials().toString());
authorizationParameters.add("client_id", "client-id");
authorizationParameters.add("client_secret", "client-secret");
authorizationParameters.add("grant_type", "password");
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(authorizationParameters, headers);
final RestTemplate restTemplate = restTemplateBuilder.rootUri(issuer).build();
try {
final ResponseEntity<DefaultOAuth2AccessToken> tokenResponseEntity = restTemplate.postForEntity("/protocol/openid-connect/token", request, DefaultOAuth2AccessToken.class, Collections.emptyMap());
if (tokenResponseEntity.getBody() != null) {
return new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), "N/A", Collections.emptyList());
}
} catch (HttpClientErrorException e) {
log.info(e.getMessage(), e);
throw e;
}
return null;
}
@Override
public boolean supports(Class<?> authentication) {
return true;
}
}