对于一组受保护的资源,如何对发布请求使用一种身份验证,对于GET请求使用另一种身份验证?

时间:2020-09-21 21:39:47

标签: spring spring-security

我正在尝试通过OAuth或基本身份验证来保护一组资源(/ admin / **)。我已经成功地单独实现了这两个(使用@Order的两个差异WebSecurityAdapters)或一起实现了(一个WebSecurityAdapter)。但是,我需要使用或。

我目前的策略是对/ admin / **的POST使用基本身份验证,而对相同URL的GET使用OAuth。这可行吗?还是有另一种方法可以做到这一点?

或者是否有办法使对/ admin / **的所有请求都需要OAuth,除非有人通过基本身份验证进行了验证-并且有一种方法可以对将正确填充SecurityContext的其他URL进行基本身份验证,因此如果执行了基本身份验证,那么对/ admin / **的访问是否也不会进行OAuth?

OAuth或基本身份验证的当前实现(取决于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;
    }
}

2 个答案:

答案 0 :(得分:0)

您可以如下定义安全适配器:

@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请求使用BASIC Auth,GET请求使用OAUTH。

答案 1 :(得分:0)

您可以定义一个自定义请求匹配器以检查基本身份验证:

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) &&  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);
}