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

使用spring boot实现双向SSL

卢文博
2023-03-14

我正在创建一些restful Web服务,并使用Spring-Boot创建一个嵌入式tomcat容器。

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

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

    System.out.println("CONFIGURED");

    http
        // ...
        .requiresChannel()
            .anyRequest().requiresSecure();
}

我似乎找不到一种方法来使Web服务仅可供提供有效客户端证书的应用程序访问。

我只有SSL的基本知识,所以即使是正确方向的一般指针也将不胜感激。

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

共有2个答案

龙承颜
2023-03-14

您可以配置clientAuth=wan,请参阅Apache Tomcat 8配置参考:

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

然后使用Spring Security-X.509身份验证读取客户端证书:

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

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

简培
2023-03-14

我遇到了一个类似的问题,并想分享我的解决方案。

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

我与您略有不同的是,我正在将我的spring boot应用程序打包到WAR归档中,然后将其部署到现有的Tomcat应用程序服务器上。

我的Tomcat服务器。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” />

小注释以避免任何混淆:keystoreFile包含用于SSL的证书/私钥对(仅限),而TrustellFile包含允许用于客户端SSL身份验证的CA证书(请注意,您也可以将客户端证书直接添加到该信任存储中)。

如果您在Spring boot应用程序中使用嵌入式tomcat容器,您应该能够使用以下属性键/值在应用程序的属性文件中配置这些设置:

server.ssl.key-store=/opt/tomcat/conf/key-stores/ssl-keystore.jks
server.ssl.key-store-password=some-complex-password
server.ssl.trust-store=/opt/tomcat/conf/trust-stores/ssl-truststore.jks
server.ssl.trust-store-password=some-other-complex-password
server.ssl.client-auth=want

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

@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(例如在我的Application的主类中):

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

@Bean
public UserDetailsService userDetailsService () {

    return new UserDetailsService() {

        @Override
        public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException {
            if (username.equals(ALLOWED_USER)) {
                final User user = new User(username, "", AuthorityUtils.createAuthorityList("ROLE_SSL_USER"));
                return user;
            }
            return null;
        }
    };
}

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

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

  1. 用户提供SSL证书;
  2. Tomcat根据其信任存储进行验证;
  3. 自定义WebSecurityConfigrerAdapter从证书的CN中检索“用户名”;
  4. 应用程序验证与检索到的用户名关联的用户;
  5. 在方法级别,如果使用@PreAuthorize("hasRole('SSL_USER')")进行注释,应用程序将检查用户是否具有所需的角色。
 类似资料:
  • 我有双向映射(@OneToMany Hibernate)和额外的方法来确保两个对象链接。简单的例子: 制图员: 生成: 主要问题:如何强制Mapalyt使用来保持父级和子级列表之间的双向映射。 我有一个更复杂的结构,有多个嵌套的子级,所以要考虑可扩展性。

  • 控制器: 存储库: 序列:

  • 本文向大家介绍Android使用DrawerLayout实现仿QQ双向侧滑菜单,包括了Android使用DrawerLayout实现仿QQ双向侧滑菜单的使用技巧和注意事项,需要的朋友参考一下 1、概述 之前写了一个Android 高仿 QQ5.0 侧滑菜单效果 自定义控件来袭 ,恰逢QQ5.2又加了一个右侧菜单,刚好看了下DrawerLayout,一方面官方的东西,我都比较感兴趣;另一方面,这玩意

  • 本文向大家介绍Vue实现双向数据绑定,包括了Vue实现双向数据绑定的使用技巧和注意事项,需要的朋友参考一下 Vue实现双向数据绑定的方式,具体内容如下 Vue是如何实现双向数据绑定的呢?答案是前端数据劫持。其通过Object.defineProperty()方法,这个方法可以设置getter和setter函数,在setter函数中,就可以监听到数据的变化,从而更新绑定的元素的值。 实现对象属性变化

  • 本文向大家介绍vue使用Proxy实现双向绑定的方法示例,包括了vue使用Proxy实现双向绑定的方法示例的使用技巧和注意事项,需要的朋友参考一下 前言:vue3.0要用Proxy来实现双向绑定,因此先来尝试一下实现方法。 1 Object.defineProperty 实现 原来vue2的实现使用Object.defineProperty,监听set,但对于数组直接下标给数组设置值监听不了。 2