2015-11-19 6 views
7

私はいくつかの快適なWeb​​サービスを作成しており、Spring-Bootを使用して埋め込みのtomcatコンテナを作成しています。スプリングブートを使用した2ウェイSSLの実装

要件の1つは、これが2方向SSLを実装することです。私はHttpSecurityオブジェクトを見てきたし、これを使用してSSLチャネルを介してWebサービスを実行するだけにそれを得ることができます: -

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

    System.out.println("CONFIGURED"); 

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

を私は見つけることができないよう何をWebサービスにのみアクセスできるようにする方法です。有効なクライアント証明書を提供するアプリケーションに送信します。

私はSSLの基本知識しか持っていないので、正しい方向の一般的なポインタでさえ評価されます。

これに配備されているサーバーには複数のアプリケーションがありますが、これは双方向SSLでロックダウンする必要がある唯一のアプリケーションです。私が本当に探しているのは、単一のアプリケーションをクライアント証明書だけを受け入れるようにロックする方法です。

+0

お返事ありがとうございます。提供されたリンクは、Tomcat 7の完全なロックダウンのようですが、これが展開されるサーバーは共有リソースなので、セキュリティ保護されたアイテムとセキュリティで保護されていないアイテムが混在しています。私が本当に探しているのは、Spring Securityとクライアント証明書を使用して単一のWebアプリケーションをロックする方法です。 –

+0

それでは、Spring Bootの組み込みのTomcatコンテナにもっと詳しく調べる必要があります。 –

答えて

4

あなたは、clientAuth=wantを設定Apache Tomcat 8 Configuration Referenceを見ることができる:true

セットを使用すると、SSLスタックが接続を受け入れる前に、クライアントから有効な証明書チェーンを必要とする場合。 SSLスタックでクライアント証明書を要求する場合はwantに設定しますが、提示されていない場合は失敗しません。クライアントがCLIENT-CERT認証を使用するセキュリティ制約によって保護されたリソースを要求しない限り、false値(デフォルト)は証明書チェーンを必要としません。その後、

Spring Security - X.509 Authenticationでクライアント証明書をお読みください。

あなたはまた、「相互認証」でSSLを使用することができます。サーバーはSSLハンドシェイクの一部としてクライアントから有効な証明書を要求します。サーバーは、その証明書が受け入れ可能な機関によって署名されていることを確認することによって、クライアントを認証します。有効な証明書が提供されている場合は、アプリケーション内のサーブレットAPIを通じて取得できます。 Spring Security X.509モジュールは、フィルタを使用して証明書を抽出します。証明書をアプリケーション・ユーザーにマップし、そのユーザーの許可された権限のセットを標準のSpring Securityインフラストラクチャーで使用するためにロードします。あなたはまだ、クライアントが証明書を提供していない場合でも、SSL接続が成功するかどう

clientAuthwantに設定することができます。証明書を提示しないクライアントは、フォーム認証などのX.509以外の認証メカニズムを使用しない限り、Spring Securityによって保護されたオブジェクトにアクセスすることはできません。

4

私は同様の問題に遭遇し、私が来た解決策を共有すると思いました。

まず、SSL証明書の認証がウェブサーバー側で処理されることを理解する必要があります(cfur。durの説明、「clientAuth = want」設定)。 次に、提供された(許可された)証明書を処理し、ユーザーにマップするためにWebアプリケーションを構成する必要があります。

私はあなたと少し違いますが、私は春のブートアプリケーションを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” /> 

小型コメント:truststoreFileが含まれている一方でいるkeystoreFileは、SSLのために使用される証明書/秘密鍵のペア(のみ)が含まれていクライアントSSL認証用の許可されたCA証明書(クライアント証明書をその信頼ストアに直接追加することもできます)。あなたは春のブートアプリケーションと組み込み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"); 
} 

}

私はその後、UserDetailsS​​ervice Bを宣言する必要があります例えば、私のアプリケーションのメインクラス):

@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_SSL_USER')")アノテーションを追加できます。次のように

少し物事をまとめると、認証フローは次のようになります。

  1. ユーザーは、SSL証明書を提供します。
  2. Tomcatは、その信頼ストアに対して検証します。
  3. カスタムWebSecurityConfigurerAdapterは、証明書のCNから「username」を取得します。
  4. アプリケーションは、取得したユーザ名に関連付けられたユーザを認証します。
  5. メソッドレベルで@PreAuthorize( "hasRole( 'SSL_USER')")でアノテーションを付けた場合、アプリケーションはユーザーに必要な役割があるかどうかをチェックします。
関連する問題