X.509证书认证最常见的使用方法是使用SSL验证服务器的身份,通常情况是在浏览器使用SSL。 浏览器使用一个它维护的可信任的证书权限列表,自动检测服务器发出的证书(比如数字签名)。
你也可以使用SSL进行“mutual authentication”相互认证;服务器会从客户端请求一个合法的证书,作为SSL握手协议的一部分。 服务器将验证客户端,通过检测它被签在一个可接受的权限里的认证。 如果已经提供了一个有效的证书,就可以从程序的servlet API里获得。 Spring Security X.509模块使用过滤器确认证书。 它将证书映射为应用程序的用户,并使用标准的Spring Security基础设施读取用户的已授予权限集合。
你应该很熟悉使用证书,在使用Spring Security之前为你的servlet容器启动客户端认证。
大多数工作都是创建和安装合适的证书和密匙。
比如,如果你使用tomcat,可以阅读这里的教程http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html
。
在你把它用在Spring Security里之前,先知道它是怎么工作,是很重要的。
启用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。如果你的application context里只定义了一个bean,就不需要使用它。
subject-principal-regex
应该包含一个单独的组。
比如默认的表达式"CN=(.*?),"匹配普通的名字字段。
所以,如果证书主题名是"CN=Jimi Hendrix, OU=...",就会得到一个名叫"Jimi Hendrix"的用户。
这个匹配是大小写不敏感的。
所以"emailAddress=(.?),"也会匹配"EMAILADDRESS=jimi@hendrix.org,CN=...",得到一个"jimi@hendrix.org"用户名。
如果客户端给出一个证书,并成功获得了一个合法用户名,然后在安全环境里应该有一个有效的Authentication
对象。
如果没有找到证书,或没有找到对应的用户,安全环境会保持为空。
这说明你可以很简单的和其他选项一起使用X.509认证,比如基于表单登录。
在Spring Security项目的samples/certificate
目录下,有几个已经生成好的证书。
如果你不想自己去生成,就可以使用们启用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链接也能成功。
客户端不提供证书的话,就不能访问Spring Security的任何安全对象,除非你使用了非X.509认证机制,比如表单认证。