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
用の
認証局
のインストール例は次のようになります。
-
アドレスバーに「
about:preferences
」と入力します. -
詳細 – >証明書 – >証明書の表示 – >認証機関
を開きます. -
Import
をクリック -
Baeldung tutorials
フォルダーとそのサブフォルダーを見つけます.
spring-security-x509/keystore
。
ca.crt
ファイルを選択して、
OK
をクリックします。
-
「
この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
は提供された
UserDetailsService
で一致するユーザーを探します。そのため、デモユーザーを1人含むこのサービスインターフェイスも実装します。
-
ティップ:** 本番環境では、この
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"));
}
}
};
}
}
前述のように、コントローラで
式ベースのアクセス制御
を使用できるようになりました。具体的には、
@ 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サイトを開くことが拒否されたことがわかります。そのため、ここで概説した
クライアント証明書
をインストールする必要があります。
-
アドレスバーに「
about:preferences
」と入力します. -
Advanced – > View Certificates – > Your Certificates
を開きます. -
Import
をクリック -
Baeldung tutorials
フォルダーとそのサブフォルダーを見つけます.
spring-security-x509/keystore
。
cid.p12
ファイルを選択して、
OK
をクリックします。
-
証明書のパスワードを入力して
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
.