# X.509 认证

## 概述

X.509 证书身份验证最常见的用途是在使用 SSL 时验证服务器的身份，最常见的是在使用浏览器中的 HTTPS 时。浏览器将自动检查服务器提供的证书是否已由其维护的可信证书颁发机构列表中的一个颁发（即数字签名）。

你还可以使用带有“相互身份验证”的 SSL；然后，服务器将从客户机请求有效的证书，作为 SSL 握手的一部分。服务器将通过检查其证书是否由可接受的权威机构签名来对客户端进行身份验证。如果提供了有效的证书，则可以通过应用程序中的 Servlet API 获得该证书。 Spring 安全 X.509 模块使用一个过滤器提取证书。它将证书映射到应用程序用户，并加载该用户的一组授权权限，以便与标准 Spring 安全基础设施一起使用。

在尝试使用 Spring 安全性的容器之前，你应该熟悉使用证书和为 Servlet 容器设置客户端身份验证。大部分工作是创建和安装合适的证书和密钥。例如，如果你正在使用 Tomcat，那么请阅读这里的说明[https://tomcat.apache.org/tomcat-9.0-doc/ssl-howto.html](https://tomcat.apache.org/tomcat-9.0-doc/ssl-howto.html)。重要的是，在尝试使用 Spring 安全措施之前，你要让它发挥作用。

## 将 X.509 身份验证添加到 Web 应用程序中

启用 X.509 客户端身份验证非常简单。只需将`<x509/>`元素添加到你的 HTTP 安全名称空间配置中。

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

该元素有两个可选属性：

* `subject-principal-regex`。用于从证书的主题名称中提取用户名的正则表达式。默认值如上所示。这是将传递给`UserDetailsService`的用户名，用于为用户加载权限。

* `user-service-ref`。这是用于 x.509 的`UserDetailsService`的 Bean ID。如果在你的应用程序上下文中只定义了一个，那么它就不需要了。

`subject-principal-regex`应该包含一个组。例如，默认表达式“cn=（.\*？），”与 Common Name 字段匹配。因此，如果证书中的主题名称是“CN=Jimi Hendrix，ou=…”，则将给出一个用户名为“Jimi Hendrix”。这些匹配不区分大小写。所以“emailaddress=（.\*？），”将匹配“emailaddress=[[[email protected]]（/cdn-cgi/l/email-protection#244e4d494d644c414a40564d5c0a4b5643），cn=…”给用户名“[[email protected]]（/cdn-cgi/l/email-protection#1a707377735a727f747e6873623475687d）”。如果客户机提供了一个证书，并且成功提取了一个有效的用户名，那么在安全上下文中应该有一个有效的`Authentication`对象。如果找不到证书，或者找不到相应的用户，那么安全上下文将保持为空。这意味着你可以轻松地使用 X.509 身份验证和其他选项，例如基于表单的登录。

## 在 Tomcat 中设置 SSL

在[Spring Security Samples repository](https://github.com/spring-projects/spring-security-samples/tree/5.6.x/servlet/java-configuration/authentication/x509/server)中有一些预先生成的证书。如果你不想生成自己的 SSL，你可以使用这些工具来启用 SSL 进行测试。文件`server.jks`包含服务器证书、私钥和颁发证书的机构证书。示例应用程序中还为用户提供了一些客户机证书文件。你可以在浏览器中安装这些功能，以启用 SSL 客户机身份验证。

要在 SSL 支持下运行 Tomcat，将`server.jks`文件放入 Tomcat `conf`目录，并将以下连接器添加到`server.xml`文件中

```
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" scheme="https" secure="true"
			clientAuth="true" sslProtocol="TLS"
			keystoreFile="${catalina.home}/conf/server.jks"
			keystoreType="JKS" keystorePass="password"
			truststoreFile="${catalina.home}/conf/server.jks"
			truststoreType="JKS" truststorePass="password"
/>
```

`clientAuth`也可以设置为`want`，如果你仍然希望 SSL 连接成功，即使客户机不提供证书。除非使用非 X.509 身份验证机制（如表单身份验证），否则不提供证书的客户端将无法访问受 Spring 安全性保护的任何对象。

[CAS](cas.html)[Run-As](runas.html)

