Grails 中基于 RESTful 证书的 (X509) 登录身份验证

Posted

技术标签:

【中文标题】Grails 中基于 RESTful 证书的 (X509) 登录身份验证【英文标题】:RESTful Certificate-Based (X509) Login Authentication in Grails 【发布时间】:2014-07-11 12:04:06 【问题描述】:

我想在 Grails 讲 REST 中设置基于证书的登录身份验证。

按照 Burt Beckwith 的文档,我使用 Spring Security Plugin (spring-security-core:2.0-RC3) 来设置 X509 身份验证:

grails.plugin.springsecurity.userLookup.userDomainClassName = 'de.app.User'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'de.app.UserRole'
grails.plugin.springsecurity.authority.className = 'de.app.Role'
grails.plugin.springsecurity.useX509 = true
grails.plugin.springsecurity.portMapper.httpsPort = "8443"
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
    '/':                              ['permitAll'],
    '/index':                         ['permitAll'],
    '/index.gsp':                     ['permitAll'],
    '/**/js/**':                      ['permitAll'],
    '/**/css/**':                     ['permitAll'],
    '/**/images/**':                  ['permitAll'],
    '/**/favicon.ico':                ['permitAll']
]

证书文件的生成和 Tomcat 配置似乎有点棘手,但在another answer 中已经指出。我这样做了,并且使用当前标准我必须配置 Tomcat 7,首先是 keystoreFile、keystorePass 和 clientAuth。我无法直接访问 server.xml。因此,我必须另找地方。与此相关的Tomcat plugin's configuration 看起来仅限于参数 keystorePath 和 keystorePassword。我通过将其添加到 BuildConfig 来尝试一下:

grails.tomcat.keystorePath = "$basedir/grails-app/conf/server.jks"
grails.tomcat.keystorePassword = "password"

不知道这两行是否足够。我找到了这个solution setting more connector arguments ,但显然事件不再被触发,所以代码没有效果。

我找到了三种使用证书请求的方法,即 Firefox、cURL 和 wget。没有工作!在我的 Grails 应用程序中记录所有内容,我发现 Spring Security 中显然没有证书到达:

web.FilterChainProxy /vehicle at position 3 of 9 in additional filter chain; firing Filter: 'X509AuthenticationFilter'
x509.X509AuthenticationFilter Checking secure context token: null
x509.X509AuthenticationFilter No client certificate found in request.
x509.X509AuthenticationFilter No pre-authenticated principal found in request

卷曲请求:

curl -v -H "Content-Type: application/xml" --cert ./username.p12 -k -i https://localhost:8443/de.app/vehicle

及其替代方案:

wget —v --header='Content-Type: application/xml' --certificate='./username.p12' --no-check-certificate -S https://localhost:8443/de.app/vehicle

(我想解决 Mac OS X Mavericks 上 curl 中的一个错误。)响应始终是 403(禁止):

* Adding handle: conn: 0x7f840280fe00
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7f840280fe00) send_pipe: 1, recv_pipe: 0
* About to connect() to localhost port 8443 (#0)
*   Trying ::1...
* Connected to localhost (::1) port 8443 (#0)
* TLS 1.0 connection using TLS_RSA_WITH_AES_128_CBC_SHA
* Server certificate: Web Server
> GET /de.app/vehicle HTTP/1.1
> User-Agent: curl/7.30.0
> Host: localhost:8443
> Accept: */*
> Content-Type: application/xml
> 
< HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
* Server Apache-Coyote/1.1 is not blacklisted
< Server: Apache-Coyote/1.1

我做错了什么?证书尚未发送或未从请求中正确获取证书。我相信后者。任何猜测我可以更深入地了解吗?

【问题讨论】:

【参考方案1】:

您需要告诉 Tomcat 您想对 SSL 使用客户端身份验证。除了您已经添加到 BuildConfig 的密钥库配置之外,添加以下内容:

grails.tomcat.clientAuth = "want"

grails.tomcat.clientAuth = "true"

如果证书不存在,第一个将不会自动失败,而 true 值会。

此外,如果您计划为您的客户端使用自签名证书,您将需要创建一个受信任的密钥库并配置 Tomcat 以使用它。

grails.tomcat.truststorePath = "$grailsSettings.baseDir/conf/ssl/server/truststore.jks"
grails.tomcat.truststorePassword = "changeit"

【讨论】:

以上是关于Grails 中基于 RESTful 证书的 (X509) 登录身份验证的主要内容,如果未能解决你的问题,请参考以下文章

Grails + RESTful URL 映射 + 过滤器 + 路由

Grails 和 Spring Security & Facebook & Oauth2 - Restful 服务器

RESTful API / MVC 应用程序的 Grails 与 JAX-RS

对于 Java 中的 RESTful 服务,JAX-RS 是不是比 Swing、Grails 或 Play 等 MVC 框架更好?

Grails 包绕过证书

Java中HTTP接口请求与HTTPS证书验证问题