Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/386.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用springboot实现双向SSL_Java_Ssl_Spring Security_Spring Boot_Tomcat8 - Fatal编程技术网

Java 使用springboot实现双向SSL

Java 使用springboot实现双向SSL,java,ssl,spring-security,spring-boot,tomcat8,Java,Ssl,Spring Security,Spring Boot,Tomcat8,我正在创建一些RESTfulWeb服务,并使用SpringBoot创建一个嵌入式tomcat容器 其中一个要求是实现双向SSL。我一直在研究HttpSecurity对象,可以通过以下方法使其仅在SSL通道上运行Web服务:- @Override protected void configure(HttpSecurity http) throws Exception { System.out.println("CONFIGURED"); http // ...

我正在创建一些RESTfulWeb服务,并使用SpringBoot创建一个嵌入式tomcat容器

其中一个要求是实现双向SSL。我一直在研究HttpSecurity对象,可以通过以下方法使其仅在SSL通道上运行Web服务:-

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

    System.out.println("CONFIGURED");

    http
        // ...
        .requiresChannel()
            .anyRequest().requiresSecure();
}
我似乎找不到一种方法,使Web服务仅可供提供有效客户端证书的应用程序访问

我只有SSL的基本知识,所以即使是一个正确方向的一般指针也会很感激


部署到的服务器将混合使用多种应用程序—这是唯一需要使用双向SSL锁定的应用程序。我真正想要的是一种锁定单个应用程序的方法,只接受客户端证书

您可以配置
clientAuth=want
,请参阅:

如果希望SSL堆栈在接受连接之前需要来自客户端的有效证书链,请设置为
true
。如果希望SSL堆栈请求客户端证书,请设置为
want
,但如果未提供客户端证书,则不会失败。
false
值(默认值)不需要证书链,除非客户端请求受使用
client-CERT
身份验证的安全约束保护的资源

然后使用以下命令读取客户端证书:

您还可以将SSL与“相互身份验证”一起使用;然后,服务器将从客户端请求有效证书,作为SSL握手的一部分。服务器将通过检查其证书是否由可接受的机构签名来验证客户端。如果提供了有效的证书,则可以通过应用程序中的ServletAPI获取该证书。Spring Security X.509模块使用过滤器提取证书。它将证书映射到应用程序用户,并加载该用户的一组授权权限,以便与标准的Spring安全基础架构一起使用

clientAuth
也可以设置为
want
,如果您仍然希望SSL连接成功,即使客户端没有提供证书。除非您使用非X.509身份验证机制,例如表单身份验证,否则不提供证书的客户端将无法访问由Spring Security保护的任何对象


我遇到了一个类似的问题,我想我会分享我带来的解决方案

首先,您需要了解SSL证书身份验证将在web服务器端处理(cfr.dur的解释,带有“clientAuth=want”设置)。 然后,必须配置您的web应用程序,以便处理提供的(和允许的)证书、将其映射到用户等

我与您之间的一个细微差别是,我正在将我的spring boot应用程序打包到WAR归档中,然后将其部署到现有的Tomcat应用程序服务器上

我的Tomcat的server.xml配置文件定义了一个HTTPS连接器,如下所示:

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
    maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
    keystoreFile="/opt/tomcat/conf/key-stores/ssl-keystore.jks"
    keystorePass=“some-complex-password“
    clientAuth="want" sslProtocol="TLS"
    truststoreFile="/opt/tomcat/conf/trust-stores/ssl-truststore.jks"
    truststorePass=“some-other-complex-password” />
@Configuration
@EnableWebSecurity
//In order to use @PreAuthorise() annotations later on...
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SSLAuthConfiguration extends WebSecurityConfigurerAdapter {

    @Value("${allowed.user}")
    private String ALLOWED_USER;

    @Value("${server.ssl.client.regex}")
    private String CN_REGEX;

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure (final HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
                .authorizeRequests()
                .antMatchers("/url-path-to-protect").authenticated() //Specify the URL path(s) requiring authentication...
            .and()
                .x509() //... and that x509 authentication is enabled
                    .subjectPrincipalRegex(CN_REGEX)
                    .userDetailsService(userDetailsService);
    }

    @Autowired
    //Simplified case, where the application has only one user...
    public void configureGlobal (final AuthenticationManagerBuilder auth) throws Exception {
        //... whose username is defined in the application's properties.
        auth
            .inMemoryAuthentication()
                .withUser(ALLOWED_USER).password("").roles("SSL_USER");
    }

}
然后,在我的web应用程序上,我声明了一个特定的SSL配置,如下所示:

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
    maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
    keystoreFile="/opt/tomcat/conf/key-stores/ssl-keystore.jks"
    keystorePass=“some-complex-password“
    clientAuth="want" sslProtocol="TLS"
    truststoreFile="/opt/tomcat/conf/trust-stores/ssl-truststore.jks"
    truststorePass=“some-other-complex-password” />
@Configuration
@EnableWebSecurity
//In order to use @PreAuthorise() annotations later on...
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SSLAuthConfiguration extends WebSecurityConfigurerAdapter {

    @Value("${allowed.user}")
    private String ALLOWED_USER;

    @Value("${server.ssl.client.regex}")
    private String CN_REGEX;

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure (final HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
                .authorizeRequests()
                .antMatchers("/url-path-to-protect").authenticated() //Specify the URL path(s) requiring authentication...
            .and()
                .x509() //... and that x509 authentication is enabled
                    .subjectPrincipalRegex(CN_REGEX)
                    .userDetailsService(userDetailsService);
    }

    @Autowired
    //Simplified case, where the application has only one user...
    public void configureGlobal (final AuthenticationManagerBuilder auth) throws Exception {
        //... whose username is defined in the application's properties.
        auth
            .inMemoryAuthentication()
                .withUser(ALLOWED_USER).password("").roles("SSL_USER");
    }

}
然后我需要声明UserDetailsService bean(例如,在我的应用程序的主类中):

就这样!然后,我可以将@PreAuthorize(“hasRole('ROLE\u SSL\u USER'))注释添加到我想要保护的方法中

总而言之,身份验证流程如下所示:

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
    maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
    keystoreFile="/opt/tomcat/conf/key-stores/ssl-keystore.jks"
    keystorePass=“some-complex-password“
    clientAuth="want" sslProtocol="TLS"
    truststoreFile="/opt/tomcat/conf/trust-stores/ssl-truststore.jks"
    truststorePass=“some-other-complex-password” />
@Configuration
@EnableWebSecurity
//In order to use @PreAuthorise() annotations later on...
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SSLAuthConfiguration extends WebSecurityConfigurerAdapter {

    @Value("${allowed.user}")
    private String ALLOWED_USER;

    @Value("${server.ssl.client.regex}")
    private String CN_REGEX;

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure (final HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
                .authorizeRequests()
                .antMatchers("/url-path-to-protect").authenticated() //Specify the URL path(s) requiring authentication...
            .and()
                .x509() //... and that x509 authentication is enabled
                    .subjectPrincipalRegex(CN_REGEX)
                    .userDetailsService(userDetailsService);
    }

    @Autowired
    //Simplified case, where the application has only one user...
    public void configureGlobal (final AuthenticationManagerBuilder auth) throws Exception {
        //... whose username is defined in the application's properties.
        auth
            .inMemoryAuthentication()
                .withUser(ALLOWED_USER).password("").roles("SSL_USER");
    }

}
  • 用户提供SSL证书
  • Tomcat根据其信任存储进行验证
  • 自定义WebSecurity配置适配器从证书的CN检索“用户名”
  • 应用程序验证与检索到的用户名关联的用户
  • 在方法级别,如果使用@PreAuthorize(“hasRole('SSL_USER'))注释,应用程序将检查用户是否具有所需的角色

  • 谢谢你的回复。提供的链接似乎是为了完全锁定tomcat 7,但是将在其上部署的服务器是一个共享资源,因此将在其上混合使用安全和非安全项目。我真正想要的是一种使用Spring Security和客户端证书锁定单个web应用程序的方法。因此,我可能需要进一步了解Spring Boot中嵌入的tomcat容器。对于我来说,使用Spring Boot 2.3.4可以节省我很多时间