в нашем проекте мы используем аутентификацию oauth2, если пользователь вызывает API с токеном носителя.
Если пользователь вызывает API с базовой аутентификацией, я могу добавить второй securityConfig для базовой аутентификации. Но как я могу аутентифицировать этого пользователя basicAuth с провайдером oauth2?
Я пытался с 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;
}
}