#spring #spring-boot #spring-security #oauth-2.0 #spring-security-oauth2
#spring #spring-boot #spring-безопасность #oauth-2.0 #spring-security-oauth2
Вопрос:
Легко ли настраивается в Spring Security, чтобы приложение использовало 2 разных grant_type?
Наше приложение Java BE предназначено для использования двумя разными пользователями через приложение Angular FE. Тип пользователя определяется как заголовок запроса:
- Сотрудники: Должны проходить аутентификацию с помощью authorization_code.
- Обычные пользователи в Интернете: они аутентифицируются через client_credentials.
Нам удалось определить это в application.properties:
#employee user
spring.security.oauth2.client.registration.employee.authorization-grant-type=authorization_code
spring.security.oauth2.client.provider.employee.authorization-uri=https://saml.company.com/oauth/authorize
spring.security.oauth2.client.registration.employee.redirect-uri=https://appDomain.com/appContext/login/oauth2/code/employee
spring.security.oauth2.client.provider.employee.token-uri=https://saml.company.com/oauth/token
spring.security.oauth2.client.registration.employee.scope=theScope
spring.security.oauth2.client.registration.employee.client-id=CLIENT_ID1
spring.security.oauth2.client.registration.employee.client-secret=SECRET
#general user
spring.security.oauth2.client.registration.direct.authorization-grant-type=client_credentials
spring.security.oauth2.client.provider.direct.token-uri=https://saml.company.com/oauth/token
spring.security.oauth2.client.registration.direct.client-id=CLIENT_ID2
spring.security.oauth2.client.registration.direct.client-secret=SECRET
Основная проблема заключается в том, что неподтвержденные вызовы для обоих типов пользователей (сотрудники и обычные пользователи) перенаправляются на стандартную страницу Spring / login, на которой отображаются 2 HTML-ссылки привязки к двум различным потокам / grant_type.
Требуемое поведение является:
- Для пользователя Employee прямое перенаправление на spring.security.oauth2.client.provider.employee.авторизация-uri для ввода его / ее учетных данных в IDP в соответствии с потоком authorization_code.
- Для обычного пользователя BE должен обрабатывать поток client_credentials, поскольку нет взаимодействия с пользователем.
Мы пытались с помощью фильтров избежать перенаправления / login, но безрезультатно. Есть идеи?
Комментарии:
1. Вы могли бы написать пользовательскую страницу входа вместо страницы входа по умолчанию.
2. Какую версию spring security вы используете? Насколько я понимаю, эта конфигурация создает два клиента oauth2 в клиентском репозитории BE apps, чтобы у вашего приложения BE могло быть два клиента oauth2 для связи с внешними серверами ресурсов oauth2. это то, что вы здесь хотите?
Ответ №1:
Вы можете определить несколько WebSecurityConfigurerAdapter, как показано ниже, для каждого отдельного URI.
@EnableWebSecurity
public class SecurityConfig {
@Configuration
@Order(1)
public static class SubscriptionWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
LOGGER.debug("SubscriptionWebSecurityConfigurerAdapter.configure start");
// Enable CORS and disable CSRF
http = http.cors().and().csrf().disable();
// Set session management to stateless
http = http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and();
// Set unauthorized requests exception handler
http = http
.exceptionHandling()
.authenticationEntryPoint(
(request, response, ex) -> {
response.sendError(
HttpServletResponse.SC_UNAUTHORIZED,
ex.getMessage()
);
}
)
.and();
http.authorizeRequests()
.antMatchers("/subs**").permitAll()
.and() ;
LOGGER.debug("SubscriptionWebSecurityConfigurerAdapter.configure end");
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().mvcMatchers("/subs**");
}
}
@Configuration
@Order(2)
public static class ManagementWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
LOGGER.debug("ManagementWebSecurityConfigurerAdapter.configure start");
http.antMatcher("/management/**")
.authorizeRequests()
.mvcMatchers("/management/monitoringService/taskmanagers").hasAnyRole("ADMIN", "OPERATOR")
.mvcMatchers("/management/sendOperationReport").hasAnyRole("ADMIN", "OPERATOR", "CONSUMER")
.anyRequest().permitAll();
LOGGER.debug("ManagementWebSecurityConfigurerAdapter.configure end");
}
}
@Order(3)
@Configuration
public static class WPSWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
private final String issuer;
public WPSWebSecurityConfigurerAdapter(OAuth2ResourceServerProperties resourceServerProps) {
this.issuer = resourceServerProps.getJwt().getIssuerUri();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
LOGGER.debug("WPSWebSecurityConfigurerAdapter.configure start");
http.antMatcher("/wps/**")
.authorizeRequests()
.mvcMatchers("/wps/WebProcessingService").authenticated()
.anyRequest().authenticated()
.and().oauth2ResourceServer()
.authenticationEntryPoint(new CustomOAuth2AuthenticationEntryPoint())
.accessDeniedHandler(new CustomOAuth2AccessDeniedHandler())
.jwt().jwtAuthenticationConverter(jwtAuthenticationConverter());
LOGGER.debug("WPSWebSecurityConfigurerAdapter.configure end");
}
@Bean
JwtDecoder jwtDecoder() {
LOGGER.debug("WPSWebSecurityConfigurerAdapter.jwtDecoder start");
NimbusJwtDecoder jwtDecoder = (NimbusJwtDecoder) JwtDecoders.fromOidcIssuerLocation(issuer);
OAuth2TokenValidator<Jwt> validatorWithIssuer = JwtValidators.createDefaultWithIssuer(issuer);
DelegatingOAuth2TokenValidator validator = new DelegatingOAuth2TokenValidator<>(validatorWithIssuer);
jwtDecoder.setJwtValidator(validator);
LOGGER.debug("WPSWebSecurityConfigurerAdapter.jwtDecoder end");
return jwtDecoder;
}
private JwtAuthenticationConverter jwtAuthenticationConverter() {
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName("authorities");
jwtGrantedAuthoritiesConverter.setAuthorityPrefix("");
JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
return jwtAuthenticationConverter;
}
}
}