Spring SecurityでのX.509認証

1概要

この記事では、 HTTPS( HTTP over SSL )プロトコルを使用する場合の X.509証明書認証__ - 通信ピアの身元の確認 の主な使用例に焦点を当てます。

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

しかしそれ以外にも、 Spring Security X.509 を使用して、接続中にサーバーを通じて クライアントの身元を確認する ことができます。これは “相互認証”と呼ばれます。 ここでもその方法について説明します。

最後に、この種の認証を使用することが意味がある場合には、ここで触れます。

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

そして、[相互認証]では、クライアント証明書を作成し、検証済みのクライアントのみを許可するようにサーバーを変更します。

2キーストア

  • オプション要件** :暗号強度の高い鍵を暗号化および復号化機能と一緒に使用するには、 JVM. にインストールされた Java Cryptography Extension(JCE)無制限強度管轄ポリシーファイル が必要です。

これらは、例えばhttp://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html[Oracle]からダウンロードできます(ダウンロードに含まれるインストール手順に従ってください)。 Linuxディストリビューションの中には、パッケージマネージャを介してインストール可能なパッケージを提供するものもあります。

Springアプリケーションで X.509認証 を実装するには、まず Java Key-Store JKS )形式の keystore を作成します。

この keystore 有効な証明書 authority または一連の証明書 authorities と私たちのサーバー用の自身の証明書を含まなければなりません。後者は含まれている authorities の一つによって署名されなければならず、そしてサーバが実行されている hostname にちなんで命名されなければなりません。ここでは Java keytool アプリケーションを使用します。

  • keytool を使って keys certificates を作成するプロセス(コードhttps://github.com/eugenp/tutorials[on Github ])は、このセクションを完成するのに必要なすべてのステップを含む、コメント付きの Makefile をGNU make に提供します。いくつかの環境変数を使って簡単にカスタマイズすることもできます。

  • ヒント:** オールインワンステップ として、引数なしで make を実行できます。

ブラウザにインポートするための keystore truststore 、および2つの証明書(1つは localhost 用、もう1つは “ cid” と呼ばれる)を作成します。

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

$> make create-keystore PASSWORD=changeit

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

$> make add-host HOSTNAME=localhost

クライアント認証 を許可するには、 "truststore" と呼ばれる keystore も必要です。この 信頼ストア は私たちの 認証局 と許可されたクライアントすべての有効な証明書を含まなければなりません。 keytool の使い方については、次のセクションの Makefile を参照してください____:

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

3アプリケーション例

SSLで保護されたサーバープロジェクトは、次のリンクで構成されます。/spring-boot-application-configuration[ @ SpringBootApplication ]アノテーション付きアプリケーションクラス-java-based-configuration[@Configuration]) application.properties__設定ファイル、そしてとてもシンプルなMVCスタイルのフロントエンド。

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

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

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <version>1.4.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>1.4.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
    <version>1.4.0.RELEASE</version>
</dependency>
  • 参考のために:** Maven Central にバンドルがあります(https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.springframework.boot%22%20AND%20a%3A %22spring-boot-starter-security%22[セキュリティ]、https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.springframework.boot%22%20AND%20a%3A %22spring-boot-starter-web%22[web]、https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.springframework.boot%22%20AND%20a%3A %22spring-boot-starter-thymeleaf%22[thymeleaf])。

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

@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 を「有効」ステータスに設定し、標準のリスニングポートを セキュアな接続を示す に変更します。

さらに、基本認証を介してサーバーにアクセスするための 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テンプレートになります。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>X.509 Authentication Demo</title>
</head>
<body>
    <h2>Hello <span th:text="${username}"/>!</h2>
</body>
</html>

このセクションを終えてサイトを見る前に、私たちが生成した認証局を私たちが選んだブラウザに 信頼できる証明書 としてインストールする必要があります。

Mozilla Firefox 用の 認証局 のインストール例は次のようになります。

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

  2. 詳細 - >証明書 - >証明書の表示 - >認証機関 を開きます.

  3. Import をクリック

  4. Baeldung tutorials フォルダーとそのサブフォルダーを見つけます.

spring-security-x509/keystore ca.crt ファイルを選択して、 OK をクリックします。

  1. このCAを信頼してWebサイトを識別させる」を選択し、 OK__

    • 注:** 認証機関 を信頼できる機関の一覧に追加したくない場合は、安全でないと記載されていても、除外__してWebサイトを厳重に表示することができます。ただし、アドレスバーに「黄色い感嘆符」の記号が表示され、安全でない接続を示しています。

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

mvn spring-boot:run

最後に、 https://localhost:8443/user にアクセスし、 application.properties からユーザーの認証情報を入力すると、「Hello Admin!」というメッセージが表示されます。これで、アドレスバーの「緑色の錠前」の記号をクリックして接続の状態を確認できるようになりました。これは安全な接続であるはずです。

リンク:/uploads/Screenshot 20160822 205015.png%20465w[]

4相互認証

このセクションでは、 Spring Security を使用してユーザーにデモWebサイトへのアクセスを許可します。この手続きはログインフォームを時代遅れにします。

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

  • 長所:**

  • __ X.509クライアント証明書の秘密鍵は 他よりも強い

ユーザー定義パスワード** しかし、それは秘密にされなければなりません!

  • 証明書を使うと、クライアントの アイデンティティ はよく知られています**

簡単に確認できます。

  • これ以上パスワードを忘れたことはありません!

  • 短所:**

  • あなたは各ユーザーに対して、によって検証されるべきであることを覚えておく必要があります

サーバーの場合は、その証明書を構成済みの truststore にインストールする必要があります。少数のクライアントしかない小規模なアプリケーションでは、これはおそらく実用的かもしれません。

証明書の秘密鍵はクライアントにインストールする必要があります。

応用。実際のところ、 X.509クライアント認証 はデバイスに依存 しているため、インターネットカフェなどの公共の場でこの種の認証を使用することは不可能です。

侵害されたクライアント証明書を無効にするメカニズムが必要です。

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

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

  • ティップ:** 本番環境では、この UserDetailsS​​ervice は、例えばリンクからそのユーザーをロードできます。/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"));
                }
            }
        };
    }
}

前述のように、コントローラで 式ベースのアクセス制御 を使用できるようになりました。具体的には、 @ Configuration : @ EnableGlobalMethodSecurity アノテーションのおかげで、私たちの認可アノテーションは尊重されます

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

考えられるすべての認証オプションの概要は、 公式文書 にあります。

最後の修正ステップとして、 truststore がどこにあり、 SSLクライアント認証 が必要かをアプリケーションに通知する必要があります( 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サイトを開くことが拒否されたことがわかります。そのため、ここで概説した クライアント証明書 をインストールする必要があります。

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

  2. Advanced - > View Certificates - > Your Certificates を開きます.

  3. Import をクリック

  4. Baeldung tutorials フォルダーとそのサブフォルダーを見つけます.

spring-security-x509/keystore cid.p12 ファイルを選択して、 OK をクリックします。

  1. 証明書のパスワードを入力して OK をクリックしてください.

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

リンク:/uploads/Screenshot 20160822 211057.png%201174w[]

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

** 5 XMLによる相互認証

**

リンクに X.509クライアント認証 を追加することもできます:/spring-security-digest-authentication[ XML のhttpセキュリティ設定]

<http>
    ...
    <x509 subject-principal-regex="CN=(.** ?)(?:,|$)"
      user-service-ref="userService"/>

    <authentication-manager>
        <authentication-provider>
            <user-service id="userService">
                <user name="cid" password="" authorities="ROLE__USER"/>
            </user-service>
        </authentication-provider>
    </authentication-manager>
    ...
</http>

基礎となる Tomcat を設定するには、 keystore truststore をその conf フォルダーに入れて server.xml を編集する必要があります。

<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" scheme="https" secure="true"
    clientAuth="true" sslProtocol="TLS"
    keystoreFile="${catalina.home}/conf/keystore.jks"
    keystoreType="JKS" keystorePass="changeit"
    truststoreFile="${catalina.home}/conf/truststore.jks"
    truststoreType="JKS" truststorePass="changeit"/>
  • ヒント:** clientAuth "want" に設定されていると、クライアントが有効な証明書を提供していなくても SSL は有効のままです。しかしこの場合、セキュリティ保護されたリソースにアクセスするために、2番目の認証メカニズム、たとえばログインフォームを使用する必要があります。

6. 結論

  • 要約** では、開発環境用に、認証局と自己署名証明書を含むキーストアを作成する方法を学びました。

認証局とクライアント証明書を含む 信頼ストアを作成しました。そして、クライアント側でサーバーを検証する とサーバー側でクライアントを検証する** 両方を使用しました。

Makefile について学んだことがあれば、 証明書 の作成、 証明書要求 の作成、および署名付き証明書のインポート をJava keytool で行うことができるはずです。

さらに、これで クライアント証明書 PKCS12 形式にエクスポート** して、ブラウザのようなクライアントアプリケーション、たとえば Mozilla Firefox で使用できるようになりました。

そして、私たちは Spring Security X.509クライアント認証 を使うことが理にかなっているときに議論しました、それであなたのWebアプリケーションにそれを実装するかどうか、決めるのはあなた次第です。

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

前の投稿:ScribeJavaへのガイド
次の投稿:Baeldungウィークリーレビュー43