java - 对同一资源使用 Oauth2 或 Http-Basic 身份验证的 Spring 安全性

标签 java security spring-security oauth-2.0 spring-security-oauth2

我正在尝试使用受 Oauth2 或 Http-Basic 身份验证保护的资源来实现 API。

当我加载首先将 http-basic 身份验证应用于资源的 WebSecurityConfigurerAdapter 时,不接受 Oauth2 token 身份验证。反之亦然。

示例配置: 这会将 http-basic 身份验证应用于所有/user/** 资源

@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private LoginApi loginApi;

    @Autowired
    public void setLoginApi(LoginApi loginApi) {
        this.loginApi = loginApi;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(new PortalUserAuthenticationProvider(loginApi));
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/users/**").authenticated()
                .and()
            .httpBasic();
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

这会将 oauth token 保护应用于/user/** 资源

@Configuration
@EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
            .requestMatchers().antMatchers("/users/**")
        .and()
            .authorizeRequests()
                .antMatchers("/users/**").access("#oauth2.clientHasRole('ROLE_CLIENT') and #oauth2.hasScope('read')");
    }
}

我确定我缺少一些魔术代码,它告诉 spring 如果第一个失败,则尝试两者?

任何帮助将不胜感激。

最佳答案

根据 Michael Ressler 的回答,我设法完成了这项工作,但做了一些调整。

我的目标是在相同的资源端点上同时允许基本身份验证和 Oauth,例如/leafcase/123。由于 filterChains 的排序,我被困了很长一段时间(可以在 FilterChainProxy.filterChains 中检查);默认顺序如下:

  • Oauth 认证服务器(如果在同一个项目中启用)的 filterChains。默认顺序 0(参见 AuthorizationServerSecurityConfiguration)
  • Oauth 资源服务器的过滤链。默认顺序 3(请参阅 ResourceServerConfiguration)。它有一个请求匹配器逻辑,可以匹配除 Oauth 身份验证端点以外的任何内容(例如,/oauth/token、/oauth/authorize 等。请参阅 ResourceServerConfiguration$NotOauthRequestMatcher.matches())。
  • config(HttpSecurity http)对应的filterChains - 默认顺序100,见WebSecurityConfigurerAdapter。

由于资源服务器的 filterChains 排名高于 WebSecurityConfigurerAdapter 配置的 filterchain,前者几乎匹配每个资源端点,因此 Oauth 资源服务器逻辑总是启动对资源端点的任何请求(即使请求使用 Authorization:Basic标题)。你会得到的错误是:

{
    "error": "unauthorized",
    "error_description": "Full authentication is required to access this resource"
}

为了完成这项工作,我做了 2 处更改:

首先,WebSecurityConfigurerAdapter 的顺序高于资源服务器(顺序 2 高于顺序 3)。

@Configuration
@Order(2)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

其次,让 configure(HttpSecurity) 使用只匹配“Authorization: Basic”的客户 RequestMatcher。

@Override
protected void configure(HttpSecurity http) throws Exception {

    http
        .anonymous().disable()
        .requestMatcher(new BasicRequestMatcher())
        .authorizeRequests()
            .anyRequest().authenticated()
            .and()
        .httpBasic()
             .authenticationEntryPoint(oAuth2AuthenticationEntryPoint())
            .and()
        // ... other stuff
 }
 ...
 private static class BasicRequestMatcher implements RequestMatcher {
    @Override
    public boolean matches(HttpServletRequest request) {
        String auth = request.getHeader("Authorization");
        return (auth != null && auth.startsWith("Basic"));
    }
 }

因此,它会在资源服务器的 filterChain 有机会匹配它之前匹配并处理 Basic Auth 资源请求。它也只处理 Authorizaiton:Basic 资源请求,因此任何带有 Authorization:Bearer 的请求都会失败,然后由资源服务器的 filterChain 处理(即 Oauth 的过滤器启动)。此外,它的排名低于 AuthenticationServer(如果在同一项目上启用了 AuthenticationServer),因此它不会阻止 AuthenticaitonServer 的过滤器链处理对/oauth/token 等的请求。

关于java - 对同一资源使用 Oauth2 或 Http-Basic 身份验证的 Spring 安全性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23526644/

相关文章:

java - Anylogic 模拟存储在容器中的 Material

用于计算唯一对象的 Java lambda 表达式

java - Spring Rest - 方法级别的自定义 header 验证

grails - grails:@Secured是否可以应用于以@Resource注释的域类?

permissions - spring-security ACL 如何授予权限

java - RestExpress - 无法看到 Infinispan 日志

java - 使用java模拟多个用户连接到Cassandra

security - 保护 dll 文件的最佳方法是什么

javascript - Electron ,contextIsolation和contextBridge

security - iframe 和 ssl 安全