Spring SecurityでのX.509認証

X.509 Authentication in Spring Security

1. 概要

この記事では、HTTPSHTTP over SSL)プロトコルを使用する場合のX.509 certificate authenticationverifying the identity of a communication peerの主な使用例に焦点を当てます。

簡単に言えば、安全な接続が確立されている間、クライアントはその証明書(信頼できる認証局によって発行された)に従ってサーバーを検証します。

ただし、それを超えると、接続中にサーバーを介してSpring SecurityX.509verify the identity of a clientに使用できます。 これは“mutual authentication, “と呼ばれ、ここでもそれがどのように行われるかを見ていきます。

最後に、when it makes sense to use this kind of authenticationについて説明します。

サーバーの検証を示すために、簡単なWebアプリケーションを作成し、ブラウザーにカスタム認証局をインストールします。

また、mutual authenticationの場合は、クライアント証明書を作成し、検証済みのクライアントのみを許可するようにサーバーを変更します。

2. キーストア

Optional Requirement:暗号化および復号化機能とともに暗号的に強力なキーを使用するには、JVM.‘Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files'をインストールする必要があります

これらは、たとえばOracleからダウンロードできます(ダウンロードに含まれているインストール手順に従ってください)。 一部のLinuxディストリビューションは、パッケージマネージャーを通じてインストール可能なパッケージも提供します。

SpringアプリケーションにX.509 authenticationを実装するには、first create a keystore in the Java Key-Store (JKS) format.を使用します。

このkeystoreは、contain a valid certificate of authority or a chain of certificate authoritiesとサーバー用の独自の証明書である必要があります。 後者は、含まれているauthoritiesのいずれかによって署名されている必要があり、サーバーが実行されているhostnameにちなんで名前が付けられている必要があります。ここでは、Javakeytoolアプリケーションを使用します。

To simplifykeytoolを使用してkeyscertificatesを作成するプロセス、コードon Githubは、GNUmakeにコメント付きのMakefileを提供します、このセクションを完了するために必要なすべてのステップが含まれています。 いくつかの環境変数を使用して簡単にカスタマイズすることもできます。

Tip:all-in-one stepとして、引数なしでmakeを実行できます。 これにより、ブラウザにインポートするためのkeystoretruststore、および2つの証明書(1つはlocalhost用、もう1つは“cid”というユーザー用)が作成されます。

認証局で新しいkeystoreを作成するには、次のようにmakeを実行できます。

$> make create-keystore PASSWORD=changeit

次に、開発ホストの証明書をこの作成されたkeystoreに追加し、certificate authorityで署名します。

$> make add-host HOSTNAME=localhost

client authenticationを許可するには、“truststore”と呼ばれるkeystoreも必要です。 このtruststoreには、certificate authorityと許可されているすべてのクライアントの有効な証明書が含まれている必要があります。 keytoolの使用に関するリファレンスについては、次のセクションでMakefileを調べてください:

$> make create-truststore PASSWORD=changeit
$> make add-client CLIENTNAME=cid

3. 応用例

SSLで保護されたサーバープロジェクトは、@SpringBootApplicationアノテーション付きアプリケーションクラス(@Configuration)の一種、application.properties構成ファイル、および非常に単純なMVCスタイルのフロントエンド)で構成されます。

アプリケーションがしなければならないのは、HTMLページに“Hello {User}!”メッセージを表示することだけです。 このようにして、ブラウザーでサーバー証明書を検査して、接続が検証および保護されていることを確認できます。

まず、3つのSpring Boot Starterバンドルが含まれる新しいMavenプロジェクトを作成します。


    org.springframework.boot
    spring-boot-starter-security
    1.4.0.RELEASE


    org.springframework.boot
    spring-boot-starter-web
    1.4.0.RELEASE


    org.springframework.boot
    spring-boot-starter-thymeleaf
    1.4.0.RELEASE

For reference:は、Maven Centralsecuritywebthymeleaf)にバンドルがあります。

次のステップとして、メインアプリケーションクラスとユーザーコントローラーを作成します。

@SpringBootApplication
public class X509AuthenticationServer {
    public static void main(String[] args) {
        SpringApplication.run(X509AuthenticationServer.class, args);
    }
}

@Controller
public class UserController {
    @RequestMapping(value = "/user")
    public String user(Model model, Principal principal) {

        UserDetails currentUser
          = (UserDetails) ((Authentication) principal).getPrincipal();
        model.addAttribute("username", currentUser.getUsername());
        return "user";
    }
}

ここで、keystoreを見つけることができる場所と、それにアクセスする方法をアプリケーションに指示します。 SSLを「有効」ステータスに設定し、標準のリスニングポートをindicate a secured connectionに変更します。

さらに、Basic Authenticationを介してサーバーにアクセスするためにいくつかのuser-detailsを構成します。

server.ssl.key-store=../keystore/keystore.jks
server.ssl.key-store-password=${PASSWORD}
server.ssl.key-alias=localhost
server.ssl.key-password=${PASSWORD}
server.ssl.enabled=true
server.port=8443
security.user.name=Admin
security.user.password=admin

これは、resources/templatesフォルダーにあるHTMLテンプレートになります。




    X.509 Authentication Demo


    

Hello !

このセクションを終了してサイトを確認する前に、生成した認証局をtrusted certificateとして選択したブラウザーにインストールする必要があります。

Mozilla Firefoxcertificate authorityのインストール例は、次のようになります。

  1. アドレスバーにabout:preferencesと入力します

  2. Advanced → Certificates → View Certificates → Authoritiesを開く

  3. Importをクリックします

  4. example tutorialsフォルダーとそのサブフォルダーspring-security-x509/keystoreを見つけます

  5. ca.crtファイルを選択し、OKをクリックします

  6. Trust this CA to identify websites”」を選択し、「OK」をクリックします

Note:certificate authoritytrusted authoritiesのリストに追加したくない場合は、後でexceptionを作成して、Webサイトをタフに表示するオプションがあります。安全でないと言われていても。 ただし、アドレスバーに「黄色の感嘆符」の記号が表示され、接続が安全でないことを示します。

その後、spring-security-x509-basic-authモジュールに移動して実行します:

mvn spring-boot:run

最後に、https://localhost:8443/userを押し、application.propertiesからユーザー資格情報を入力すると、“Hello Admin!”メッセージが表示されます。 これで、アドレスバーの「緑色の鍵」記号をクリックして接続ステータスを調べることができます。これは安全な接続である必要があります。

image

 

4. 相互認証

このセクションでは、Spring Securityを使用して、ユーザーにデモWebサイトへのアクセスを許可します。 この手順により、ログインフォームが廃止されます。

ただし、サーバーの変更を続ける前に、この種の認証を提供することが理にかなっている場合について簡単に説明します。

長所:

  • X.509 client certificateの秘密鍵はstronger than any user-defined passwordです。 しかし、それは秘密にしておかなければなりません!

  • 証明書を使用すると、クライアントのidentityis well-knownになり、簡単に確認できます。

  • これ以上パスワードを忘れません!

短所:

  • サーバーによって検証される必要があるユーザーごとに、その証明書を構成済みのtruststoreにインストールする必要があることを覚えておく必要があります。 少数のクライアントしかない小さなアプリケーションの場合、これはおそらく実用的かもしれません、with an increasing number of clients it may lead to complex key-management for users

  • 証明書の秘密キーは、クライアントアプリケーションにインストールする必要があります。 実際、X.509 client authenticationis device dependentであるため、インターネットカフェなどの公共の場所でこの種の認証を使用することはできません。

  • 侵害されたクライアント証明書を取り消すメカニズムが必要です。

続行するには、X509AuthenticationServerを変更して、WebSecurityConfigurerAdapterから拡張し、提供されているconfigureメソッドの1つをオーバーライドします。 ここでは、ユーザー名を抽出するために証明書のCommon Name (CN)フィールドを解析するようにx.509メカニズムを構成します。

この抽出されたユーザー名を使用して、Spring Securityは、提供されたUserDetailsServiceで一致するユーザーを検索しています。 そのため、1人のデモユーザーを含むこのサービスインターフェイスも実装します。

Tip:実稼働環境では、このUserDetailsServiceは、たとえばリンクからユーザーをロードできます。/spring-jdbc-jdbctemplate.

事前/事後承認が有効になっている@EnableWebSecurity@EnableGlobalMethodSecurityでクラスに注釈を付けることに注意する必要があります。

後者を使用すると、きめ細かいアクセス制御のために、リソースに@PreAuthorize@PostAuthorizeで注釈を付けることができます。

@SpringBootApplication
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class X509AuthenticationServer extends WebSecurityConfigurerAdapter {
    ...

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated()
          .and()
          .x509()
            .subjectPrincipalRegex("CN=(.*?)(?:,|$)")
            .userDetailsService(userDetailsService());
    }

    @Bean
    public UserDetailsService userDetailsService() {
        return new UserDetailsService() {
            @Override
            public UserDetails loadUserByUsername(String username) {
                if (username.equals("cid")) {
                    return new User(username, "",
                      AuthorityUtils
                        .commaSeparatedStringToAuthorityList("ROLE_USER"));
                }
            }
        };
    }
}

前に述べたように、コントローラーでExpression-Based Access Controlを使用できるようになりました。 より具体的には、@Configuration@EnableGlobalMethodSecurityアノテーションにより、承認アノテーションが尊重されます。__

@Controller
public class UserController {
    @PreAuthorize("hasAuthority('ROLE_USER')")
    @RequestMapping(value = "/user")
    public String user(Model model, Principal principal) {
        ...
    }
}

可能なすべての認証オプションの概要は、official documentation.にあります。

最終的な変更手順として、truststoreが配置されている場所と、SSL client authenticationが必要であること(server.ssl.client-auth=need)をアプリケーションに通知する必要があります。

したがって、application.propertiesに次のように入力します。

server.ssl.trust-store=../keystore/truststore.jks
server.ssl.trust-store-password=${PASSWORD}
server.ssl.client-auth=need

ここで、アプリケーションを実行し、ブラウザーでhttps://localhost:8443/userを指定すると、ピアを検証できないことが通知され、Webサイトを開くことが拒否されます。 したがって、client certificateもインストールする必要があります。これは、Mozilla Firefoxの例としてここに概説されています。

  1. アドレスバーにabout:preferencesと入力します

  2. Advanced → View Certificates → Your Certificatesを開く

  3. Importをクリックします

  4. example tutorialsフォルダーとそのサブフォルダーspring-security-x509/keystoreを見つけます

  5. cid.p12ファイルを選択し、OKをクリックします

  6. 証明書のパスワードを入力し、OKをクリックします

最後のステップとして、ウェブサイトを含むブラウザタブを更新し、新しく開いたチューザーダイアログでクライアント証明書を選択します。

image

“Hello cid!”のようなウェルカムメッセージが表示された場合、成功しました。

5. XMLによる相互認証

http security configuration in XMLX.509 client authenticationを追加することも可能です。


    ...
    

    
        
            
                
            
        
    
    ...

基になるTomcatを構成するには、keystoretruststoreconfフォルダーに配置し、server.xmlを編集する必要があります。

Tip:clientAuth“want”に設定すると、クライアントが有効な証明書を提供しなくても、SSLは有効になります。 ただし、この場合、保護されたリソースにアクセスするには、ログインフォームなどの2番目の認証メカニズムを使用する必要があります。

6. 結論

In summarycertificate authorityself-signed certificate for our development environmentを含むkeystoreを作成する方法を学びました。

truststore containing a certificate authority and a client certificateを作成し、両方を使用して、サーバー側のクライアント側のand our clientverify our serverを使用しました。

Makefileを学習した場合は、Javakeytoolを使用してcreate certificates, make certificate-requests and import signed certificatesを学習できるはずです。

さらに、export a client certificate into the PKCS12 formatを実行できるようになり、ブラウザなどのクライアントアプリケーション(Mozilla Firefoxなど)で使用できるようになります。

また、Spring Security X.509 client authenticationを使用することが理にかなっている場合について説明したので、それをWebアプリケーションに実装するかどうかを決定するのはあなた次第です。

最後に、この記事のソースコードを見つけますon Github.