当前位置: 首页 > 知识库问答 >
问题:

使用HTTP Basic和OIDC承载令牌进行Spring Security身份验证

公冶子琪
2023-03-14

我正在开发一个使用Spring Boot 2.4.1和Spring Security 5.4.2的Webhtml" target="_blank">应用程序,我需要提供HTTP基本身份验证和持有者令牌身份验证(JWT访问令牌从SPA发送用于每次API调用)。所有 API URL 都以路径 /api 开头,并且必须使用持有者令牌进行身份验证,但使用 HTTP Basic 所需的两个 URL(/api/func1 和 /api/func2)除外。

问题是如果我激活扩展WebSecurityConfigrerAdapter for HTTP Basic的类,则会跳过承载令牌身份验证。

@Configuration
@EnableWebSecurity
@ConditionalOnProperty(name = "auth.enable", matchIfMissing = true)
@Order(1)
public class HttpBasicSecurityConfiguration extends WebSecurityConfigurerAdapter {

    private final RestBasicAuthEntryPoint authenticationEntryPoint;
    private final DataSource dataSource;

    @Autowired
    public HttpBasicSecurityConfiguration(final RestBasicAuthEntryPoint authenticationEntryPoint,
                                          final DataSource dataSource) {
        super();
        this.authenticationEntryPoint = authenticationEntryPoint;
        this.dataSource = dataSource;
    }

    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        http.csrf().disable()
            .authorizeRequests().antMatchers({"/api/func1/**","/api/func2/**"}).authenticated()
            .and()
            .httpBasic()
            .authenticationEntryPoint(authenticationEntryPoint);
    }

    @Override
    protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
        // Usernames, passwords and roles are stored into USERS and AUTHORITIES tables
        auth.jdbcAuthentication()
            .passwordEncoder(passwordEncoder())
            .dataSource(dataSource);
    }

    private PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }
}

@Configuration
@EnableWebSecurity(debug=true)
@ConditionalOnProperty(name = "auth.enable", matchIfMissing = true)
@Order(2)
public class Oauth2SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    public Oauth2SecurityConfiguration(CactusSystemConfiguration systemConfiguration) {
        super();
        this.systemConfiguration = systemConfiguration;
    }

    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .authorizeRequests()
            .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
            .antMatchers({"/ws/**","/api/mock/**"}).permitAll()
            .and()
            .authorizeRequests().antMatchers("/api/**").authenticated()
            .and()
            .oauth2ResourceServer().jwt();
    }
}

当调用需要使用承载令牌进行身份验证的方法时,Spring Security debug会打印以下信息:

Request received for GET '/api/genericFunc':

org.apache.catalina.connector.RequestFacade@517df0fb

servletPath:/api/genericFunc
pathInfo:null
headers: 
host: devbox:8080
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0
accept: */*
accept-language: en-US,en;q=0.5
accept-encoding: gzip, deflate
authorization: Bearer eyJ0eXAiOiJ.....
connection: keep-alive
cookie: JSESSIONID=D3E8CED6AB13EFF0D15BFA6C69AFEED4; JSESSIONID=C923091B9B9E38A19106BC4F529F7D13


Security filter chain: [
  WebAsyncManagerIntegrationFilter
  SecurityContextPersistenceFilter
  HeaderWriterFilter
  LogoutFilter
  BasicAuthenticationFilter
  RequestCacheAwareFilter
  SecurityContextHolderAwareRequestFilter
  AnonymousAuthenticationFilter
  SessionManagementFilter
  ExceptionTranslationFilter
  FilterSecurityInterceptor
]

显然,未加载BearTokenAuthenticationFilter。

如果我从运行中排除HttpBasicSecurityConfiguration,那么我得到:

Security filter chain: [
  WebAsyncManagerIntegrationFilter
  SecurityContextPersistenceFilter
  HeaderWriterFilter
  LogoutFilter
  BearerTokenAuthenticationFilter
  RequestCacheAwareFilter
  SecurityContextHolderAwareRequestFilter
  AnonymousAuthenticationFilter
  SessionManagementFilter
  ExceptionTranslationFilter
  FilterSecurityInterceptor
]

知道为什么会这样吗?在Spring Security中,使用具有相同祖先路径(即/api)的api可能不可能有两种不同的身份验证方法

共有1个答案

贡威
2023-03-14

发生这种情况是因为HttpBasicSecurityConfiguration匹配所有请求,因此只有/api/func1/**/api/func2/**根据http基本身份验证进行检查,而其他请求不需要进行身份验证。此时跳过 Spring 安全筛选器链,并且永远不会触发另一个筛选器。

您需要限制应用第一个筛选器的请求。只需将<code>HttpBasicSecurity配置

@Override
protected void configure(final HttpSecurity http) throws Exception {
    http.csrf().disable()
            .requestMatchers().antMatchers("/api/func1/**","/api/func2/**")
            .and()
            .authorizeRequests().anyRequest().authenticated()
            .and()
            .httpBasic()
            .authenticationEntryPoint(authenticationEntryPoint);
}

请注意,.requestMatchers()。antMatchers(“/api/func1/**”和“/api/func2/**”.authorizeRequests()之前应用。anyRequest()然后您可以使用任何请求,无需再次匹配url。

 类似资料:
  • 我已经使用Jhipster生成了一个带有安全选项OAuth2.0/OIDC身份验证的应用程序。我按照http://www.jhipster.tech/security/#Okta的说明重新配置了该应用程序,使用Okta而不是keycloak。所有工作都按预期进行,登录流也按预期执行。 现在我想使用OAuth2.0access_tokens从其他客户机(Postman、Wordpress)访问我的a

  • 我正在尝试在ASP.NET5中实现OAuth承载令牌身份验证,并且正在努力寻找一个如何实现这一点的示例,因为OWIN的东西在ASP.NET5中发生了变化。 例如IApplicationBuilder.UseOAuthAuthorizationServer()和IApplicationBuilder。UseOAuthBearerAuthentication()要么不再存在,要么缺少引用? 如有任何指

  • 致命:“https://github.com/scuzzlebuzzle/ol3-1.git/'”身份验证失败

  • 我们目前正在使用Apache Camel作为集成框架设置一个Springboot项目。 在路由的最后,我们需要使用WSS websocket协议发送消息,其中我们的应用程序充当客户机,需要将消息发送到公开websocketendpoint的远程服务器。 但是远程服务器首先需要在WSS握手期间进行身份验证。事实上,它需要一些特定的HTTP头,包括头。只有在握手过程中才需要该令牌。打开websocke

  • 我正在使用带有承载策略的Passport AAD项目来保护我的endpoint。当我在登录时收到带有OIDC策略的令牌后,我似乎无法获得承载策略来验证访问令牌的签名。我得到: 我没有问题验证id_token,但如果id_token不能用AAD刷新,我更希望不要在我们的客户端应用程序中使用它。此外,当使用jwt.io测试发布的公钥的验证时,我看到了同样的问题(可以验证id_token,但不能验证ac

  • 我有一个REST API服务提供者,用PHP编写。我在《邮递员》中成功地测试了它,它在那里工作正常。 现在我要为它准备API留档,我正在使用Swagger UI 3。我正确地设置了它,我可以用顶部的授权按钮处理授权。 成功登录后,我希望endpoint设置并使用相应的承载令牌。但这不会发生,当我尝试任何endpoint时,REST服务器都会抱怨缺少授权头。我测试了网络流量,HTTP请求中没有令牌。