#spring #spring-security
#spring #spring-безопасность
Вопрос:
Я пытаюсь защитить набор ресурсов (/admin /**) с помощью OAuth или базовой аутентификации. Я успешно реализовал оба из них по отдельности (2 diff. WebSecurityAdapters с @Order) или вместе (один WebSecurityAdapter). Однако мне нужно использовать либо или.
Моей текущей стратегией для этого было бы СООБЩЕНИЕ в /admin/** использует базовую аутентификацию, а для перехода к тому же URL-адресу используется OAuth. Это выполнимо? Или есть другой способ добиться этого?
Или есть способ, чтобы все запросы к /admin/** требовали OAuth, если только кто-то не аутентифицируется с помощью Basic Auth — и есть ли способ выполнить базовую аутентификацию по другому URL, который правильно заполнял бы SecurityContext, чтобы в случае выполнения базовой аутентификации посещение /admin/** также не будет OAuth?
Текущая реализация OAuth или Basic Auth (в зависимости от того, какой из них является Order(1)):
@Configuration
@Order(2)
public class BasicAuth extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().frameOptions().sameOrigin().and().cors().and().csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and().httpBasic().and().authorizeRequests()
.antMatchers("/**/*.{js,html,css}", "/", "/api/user", "/static/css/**/*", "/static/css/*", "/static/js/*", "/static/js/**/*").permitAll()
.anyRequest().authenticated();
}
}
@EnableWebSecurity(debug = true)
@Configuration
@Order(1)
public class OAuth extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterAfter(this.oauthConsumerContextFilter(), SwitchUserFilter.class);
http.addFilterAfter(this.oauthConsumerProcessingFilter(), OAuthConsumerContextFilter.class);
}
// IMPORTANT: this must not be a Bean
OAuthConsumerContextFilter oauthConsumerContextFilter() {
OAuthConsumerContextFilter filter = new OAuthConsumerContextFilter();
filter.setConsumerSupport(this.consumerSupport());
return filter;
}
// IMPORTANT: this must not be a Bean
OAuthConsumerProcessingFilter oauthConsumerProcessingFilter() {
OAuthConsumerProcessingFilter filter = new OAuthConsumerProcessingFilter();
filter.setProtectedResourceDetailsService(this.prds());
LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> map = new LinkedHashMap<>();
// one entry per oauth:url element in xml
map.put(
// 1st arg is equivalent of url:pattern in xml
// 2nd arg is equivalent of url:httpMethod in xml
new AntPathRequestMatcher("/admin/**", null),
// arg is equivalent of url:resources in xml
// IMPORTANT: this must match the ids in prds() and prd() below
Collections.singletonList(new SecurityConfig("myResource")));
map.put(
// 1st arg is equivalent of url:pattern in xml
// 2nd arg is equivalent of url:httpMethod in xml
new AntPathRequestMatcher("/auth/setup", null),
// arg is equivalent of url:resources in xml
// IMPORTANT: this must match the ids in prds() and prd() below
Collections.singletonList(new SecurityConfig("myResource")));
filter.setObjectDefinitionSource(new DefaultFilterInvocationSecurityMetadataSource(map));
return filter;
}
@Bean // optional, I re-use it elsewhere, hence the Bean
OAuthConsumerSupport consumerSupport() {
CoreOAuthConsumerSupport consumerSupport = new CoreOAuthConsumerSupport();
consumerSupport.setProtectedResourceDetailsService(prds());
return consumerSupport;
}
@Bean // optional, I re-use it elsewhere, hence the Bean
ProtectedResourceDetailsService prds() {
return (String id) -> {
switch (id) {
// this must match the id in prd() below
case "myResource":
return prd();
}
throw new RuntimeException("Invalid id: " id);
};
}
ProtectedResourceDetails prd() {
BaseProtectedResourceDetails details = new BaseProtectedResourceDetails();
// this must be present and match the id in prds() and prd() above
details.setId("myResource");
details.setConsumerKey("asdf");
details.setSharedSecret(new SharedConsumerSecretImpl("asdf"));
details.setRequestTokenURL("<url>/oauth-request-token");
details.setUserAuthorizationURL("<url>/oauth-authorize");
details.setAccessTokenURL("<url>/oauth-access-token");
// enable oauth 1.0a
details.setUse10a(true);
// any other service-specific settings
return details;
}
}
Ответ №1:
Вы можете определить свои адаптеры безопасности, как показано ниже:
@EnableWebSecurity(debug = true)
@Configuration
@Order(1)
public class OAuth extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatcher(new AntPathRequestMatcher("/admin/**", HttpMethod.GET.toString()));
http.addFilterAfter(this.oauthConsumerContextFilter(), SwitchUserFilter.class);
http.addFilterAfter(this.oauthConsumerProcessingFilter(), OAuthConsumerContextFilter.class);
}
@Configuration
@Order(2)
public class BasicAuth extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatcher(new AntPathRequestMatcher("/admin/**", HttpMethod.POST.toString())).headers().frameOptions().sameOrigin().and().cors().and().csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and().httpBasic().and().authorizeRequests()
.antMatchers("/**/*.{js,html,css}", "/", "/api/user", "/static/css/**/*", "/static/css/*", "/static/js/*", "/static/js/**/*").permitAll()
.anyRequest().authenticated();
}
}
Приведенная выше конфигурация должна разрешать БАЗОВУЮ аутентификацию для запросов POST и OAUTH для запросов GET.
Ответ №2:
Вы могли бы определить пользовательский сопоставитель запросов для проверки базовой аутентификации :
public class BasicUrlAntPathRequestMatcher implements RequestMatcher {
private final String pattern;
public BasicUrlAntPathRequestMatcher(String pattern) {
this.pattern = pattern;
}
@Override
public boolean matches(HttpServletRequest request) {
String auth = request.getHeader(HttpHeaders.AUTHORIZATION);
boolean hasBasicToken = (auth != null) amp;amp; auth.startsWith("Basic");
return !(new AntPathRequestMatcher(this.pattern).matches(request) || hasBasicToken);
}}
И в вашем классе конфигурации OAuth вы можете добавить эту строку в конфигурацию http
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatcher(new BasicUrlAntPathRequestMatcher("your/basic/login"));
http.addFilterAfter(this.oauthConsumerContextFilter(), SwitchUserFilter.class);
http.addFilterAfter(this.oauthConsumerProcessingFilter(), OAuthConsumerContextFilter.class);
}