如何使用 spring-session 和 spring-security-oauth 保护同一个资源

How to protect the same resource using both spring-session and spring-security-oauth

我有使用两种身份验证的要求, 对于网络,我们使用@EnableRedisHttpSession,对于移动设备等其他消费者,我们使用@EnableAuthorizationServer 和@EnableResourceServer。

假设我们尝试保护两种身份验证机制共有的控制器,例如 /api/v1/test

我遇到了障碍。 我只能使用一种身份验证方案 如果我设置@WebSecurityConfigurerAdapter @order(2) 和@ResourceServerConfigurerAdapter @order(3) 那么我只能通过网络访问资源

如果我设置@ResourceServerConfigurerAdapter @order(2) 和@WebSecurityConfigurerAdapter @order(3),那么只有 OAuth 有效。

我无法同时使用这两种机制 time.how 我们能否让两者一起工作,例如,如果请求来自网络,则使用负责该机制的过滤器,如果请求来自移动设备使用适当的过滤器。 web 使用 cookie,API 消费者使用 Authorization : Bearer header。

请帮忙

听起来很奇怪。我建议您回顾一下 REST API 的使用方式以及浏览器用户应该使用它的原因。最好将 Web 视图和 REST 分开 API,不要混用。

但是,回答您的问题“我可以同时对某些 URI 使用两种身份验证吗”- 是的,您可以。
您需要自定义 RequestMatcher 来决定如何路由传入请求。

所以:

  • 对于“API 消费者”- 检查是否存在 Authorization header 包含“承载”
  • 对于“浏览器用户”- 只需反转第一条规则

代码示例:

public abstract class AntPathRequestMatcherWrapper implements RequestMatcher {

    private AntPathRequestMatcher delegate;

    public AntPathRequestMatcherWrapper(String pattern) {
        this.delegate = new AntPathRequestMatcher(pattern);
    }
    
    @Override
    public boolean matches(HttpServletRequest request) {
        if (precondition(request)) {
            return delegate.matches(request);
        }
        return false;
    }

    protected abstract boolean precondition(HttpServletRequest request);

}
  1. OAuth2 身份验证
@EnableResourceServer
@Configuration
public class ResourceServerConfigurer extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.requestMatcher(new AntPathRequestMatcherWrapper("/api/v1/test") {
            @Override
            protected boolean precondition(HttpServletRequest request) {
                return String.valueOf(request.getHeader("Authorization")).contains("Bearer");
            }
        }).authorizeRequests().anyRequest().authenticated();
    }
}
  1. 网络认证
@Configuration
@EnableWebSecurity
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatcher(new AntPathRequestMatcherWrapper("/api/v1/test") {
            @Override
            protected boolean precondition(HttpServletRequest request) {
                return !String.valueOf(request.getHeader("Authorization")).contains("Bearer");
            }
        }).authorizeRequests().anyRequest().authenticated();
    }
}

使用此配置可​​以为一个 URI 使用两种不同的身份验证类型 /api/v1/test

此外,我强烈建议阅读 Dave Syer 撰写的有关 Spring 安全架构的文章,以了解其工作原理:
https://spring.io/guides/topicals/spring-security-architecture/#_web_security