spring 如何在启用HTTP Posts的沿着启用X509相互身份验证?

q43xntqr  于 2023-05-16  发布在  Spring
关注(0)|答案(1)|浏览(110)

我有一个正在工作的SpringBoot REST服务器(使用HTTPS相互身份验证)。HTTP Get请求正在工作,现在我正在尝试HTTP Post请求工作。
当我进行POST时,我得到错误

curl $CURL_OPTS -X POST https://$CURL_HOSTS/api/my/endpoint1
{
    "error": "Forbidden",
    "path": "api/my/endpoint1",
    "status": 403,
    "timestamp": "2023-05-12T19:47:58.874+00:00"
}

我搜索并找到了这个解决方案:How to Solve 403 Error in Spring Boot Post Request
但是在添加了该解决方案中推荐的代码后,我得到了错误:

2023-05-12 21:22:00 UTC WARN  o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext -
Exception encountered during context initialization - cancelling
refresh attempt: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'springSecurityFilterChain' defined
in class path resource
[org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: 
Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: 
Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; 
nested exception is java.lang.IllegalStateException: 
Found WebSecurityConfigurerAdapter as well as SecurityFilterChain.
Please select just one.

下面是两个冲突并导致此错误的类。我正在寻找如何将两者所需的内容合并到同一个文件或同一个bean中,我不确定需要什么解决方案。

原始文件:支持X509和双向身份验证

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
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.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.SecurityFilterChain;

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Slf4j
public class X509AuthenticationServer {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .x509()
                .subjectPrincipalRegex("CN=(.*?)(?:,|$)")
                .userDetailsService(userDetailsService());
        log.info("X509AuthenticationServer: filterChain bean created");
        return http.build();
    }

    @Bean
    public UserDetailsService userDetailsService() {
        return new UserDetailsService() {
            @Override
            public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
                // Allow any user to be valid
                return new User(username, "",
                        AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER"));
            }
        };
    }
}

基于How to Solve 403 Error in Spring Boot Post Request的新增文件

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
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.web.SecurityFilterChain;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.util.Arrays;

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{

    @Override
    protected void configure(HttpSecurity http) throws Exception{
        http.cors().and().csrf().disable();
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("*"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

}

其中大部分只是从另一个项目复制/粘贴,因此指向SpringBoot或SpringWeb文档的指针可能也会有所帮助。
到目前为止,我还没有找到任何结合这两个问题的东西,所以很可能这是一个Spring概念,我需要在我的大脑中弄清楚。
注意:我已经开始尝试将这两个文件结合起来,但到目前为止还没有找到一个有效的解决方案。

Spring docs

e4yzc0pl

e4yzc0pl1#

问题是由试图定义两个SecurityFilterChain bean的代码引起的。一个在第一个代码文件中,第二个在第二个代码文件中。您需要将处理HttpSecurity对象的代码合并到一个方法中。比如说

@Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable();
        http.authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .x509()
                .subjectPrincipalRegex("CN=(.*?)(?:,|$)")
                .userDetailsService(userDetailsService());
        log.info("X509AuthenticationServer: filterChain bean created");
        return http.build();
    }

这是因为扩展WebSecurityConfigurerAdapter的代码创建了一个Filter bean。当我在IntelliJ中查看它时,我看到了以下反编译代码。

public void init(WebSecurity web) throws Exception {
        HttpSecurity http = this.getHttp();
        web.addSecurityFilterChainBuilder(http).postBuildAction(() -> {
            FilterSecurityInterceptor securityInterceptor = (FilterSecurityInterceptor)http.getSharedObject(FilterSecurityInterceptor.class);
            web.securityInterceptor(securityInterceptor);
        });
    }

相关问题