<Spring Security> 在同一应用程序中具有 OAuth2 和基本身份验证

Posted

技术标签:

【中文标题】<Spring Security> 在同一应用程序中具有 OAuth2 和基本身份验证【英文标题】:<Spring Security> Having OAuth2 and basic authentication in the same application 【发布时间】:2021-12-31 19:51:32 【问题描述】:

我有一个 SpringBoot 应用程序,主要用作 Web 应用程序。它使用 OAuth2(与 AzureAD)身份验证。现在的场景是它还需要充当 API 提供者,它使用基本身份验证。所以基本上默认是 OAuth2,除了 (/rest/api/**) 之类的模式。

以下是我搜索后的来源。

在测试时,它免除了 (/rest/api/) 模式的身份验证。我想这是由“.antMatchers("/rest/api/").permitAll()" 行引起的。但是如果省略这行,假设 (/rest/api/**) 模式将被“WebSecurityAzureConfig”拾取并需要 OAuth2 身份验证,这不是我们想要的。

任何建议和意见都非常感谢,谢谢。

package com.test.security;

import com.azure.spring.aad.webapp.AADWebSecurityConfigurerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig 

    @Autowired
    private AzureAuthenticationSuccessHandler authenticationSuccessHandler;

    @Autowired
    private AzureOidcUserService oidcUserService;

    @SuppressWarnings("deprecation")
    @Bean
    public NoOpPasswordEncoder passwordEncoder() 
        return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
    

    @Configuration
    @Order(1)
    public class WebSecurityAzureConfig extends AADWebSecurityConfigurerAdapter 
        @Override
        protected void configure(HttpSecurity http) throws Exception 
            super.configure(http);
            http.headers().frameOptions().sameOrigin()
                    .and()
                        .csrf().disable()
                        .authorizeRequests()
                        .antMatchers("/css/**").permitAll()
                        .antMatchers("/fonts/**").permitAll()
                        .antMatchers("/images/**").permitAll()
                        .antMatchers("/scripts/**").permitAll()
                        .antMatchers("/swagger-resources/**", "/swagger-ui.html", "/webjars/**", "/v2/api-docs", "/csrf").permitAll() // Swagger
                        .antMatchers("/version").permitAll()
                        .antMatchers("/healthCheck").permitAll()
                        .antMatchers("/h2-console/**").permitAll() // TODO Remove it before going to PROD
                        .antMatchers("/", "/login", "/oauth/**").permitAll()
                        .antMatchers("/rest/api/**").permitAll()
                            .anyRequest().authenticated()
                    .and()
                        .formLogin()
                        .loginPage("/login")
                    .and()
                        .oauth2Login()
                        .userInfoEndpoint()
                        .oidcUserService(oidcUserService)
                        .and()
                        .successHandler(authenticationSuccessHandler)
                    .and()
                        .logout()
                        .invalidateHttpSession(true)
                        .clearAuthentication(true)
                        .logoutSuccessUrl("/logoutSuccess")
                        .permitAll();
        
    

    @Configuration
    @Order(2)
    public class WebSecurityBasicConfig extends WebSecurityConfigurerAdapter 
        @Override
        protected void configure(HttpSecurity http) throws Exception 
            http.authorizeRequests()
                    .antMatchers("/rest/api/**").authenticated()
                    .and()
                    .httpBasic();
        
    

【问题讨论】:

参见参考文档中的Multiple HttpSecurity。你想翻转它,所以特定的模式 (http.antMatchers("/rest/api/**")...) 是第一个。 【参考方案1】:

感谢@Steve Riesenberg 的建议,

你想要多重认证(http.antMatchers("/rest/api/**").)是先执行参考JavaConfiguration :: Spring Security

尝试添加自定义权限,当用户使用基本身份验证连接时,我们称之为ROLE_BASICAUTH,当用户使用 OAuth2 连接时,我们称之为 ROLE_OAUTH2。这样,你就可以使用

.antMatchers("/endpoint-that-requires-basic-auth").hasRole("BASICAUTH")
.antMatchers("/endpoint-that-requires-oauth2").hasRole("OAUTH2")
    .anyRequest().authenticated()

当他们到达您需要基本身份验证(而不是 OAuth2)的端点时,您检查他们当前的权限,如果它不是 BASICAUTH,那么您使他们的会话无效,您会显示一个没有 OAuth2 的登录表单(以强制他们使用基本身份验证)。

更多详情请参考SO Thread:

【讨论】:

以上是关于<Spring Security> 在同一应用程序中具有 OAuth2 和基本身份验证的主要内容,如果未能解决你的问题,请参考以下文章

请教,spring security 配置

spring security

007Spring Security

spring-security安全登录

Spring Security实现记住我功能

spring security remember me实现自动登录