【问题标题】:Server-side access control using client's X509 certificate DN使用客户端 X509 证书 DN 的服务器端访问控制
【发布时间】:2015-03-18 04:32:28
【问题描述】:

人民,

我使用 JAX-RS 和 Jersey 2.17 和 Grizzly 作为我的 HTTP 服务器。我已经配置了客户端身份验证并且可以正常工作,但是,我正在尝试对客户端的 X.509 证书 DN 实施访问控制。这将为我提供与配置 Apache httpd 和 FakeBasicAuth 相同的功能。

我尝试使用 ContainerRequestFilter,但似乎找到了一种方法来获取对与 TLS 会话关联的客户端 DN 的引用。有人可以告诉我一种使用 ContainerRequestFilter 或任何其他机制访问证书以实现相同最终目标的方法吗?

编辑:我尝试了“@javax.ws.rs.core.Context HttpServletRequest req;”昨晚发布前,但 HttpServletRequest 上下文始终为空。我使用 GrizzlyHttpServerFactory 如下:

GrizzlyHttpServerFactory.createHttpServer(
                getServerURI(), getResourceConfig(), true,
                new SSLEngineConfigurator(sslContext.get())
                    .setNeedClientAuth(true).setClientMode(false))

这不是一个 servlet 容器,因此不支持 HttpServletRequest 上下文。我很快查看了 GrizzlyWebContainerFactory,但初始化完全不同,我想避免经历那种痛苦。有没有其他方法可以访问“javax.ws.rs.container.ContainerRequestFilter”中的用户证书?

谢谢!

约翰

【问题讨论】:

  • 参见 Servlet 规范。客户端证书可通过请求属性获得。

标签: java ssl jersey grizzly


【解决方案1】:

来自 Java Servlet 规范:

如果有与请求关联的 SSL 证书,则它必须由 servlet 容器作为 java.security.cert.X509Certificate 类型的对象数组公开给 servlet 程序员,并可通过 ServletRequestjavax.servlet.request.X509Certificate 的属性。

这个数组的顺序被定义为信任的升序。首先 链中的证书是由 客户,下一个 是一个习惯 验证第一个,依此类推。

实际上,这意味着:

X509Certificate[] certs = (X509Certificate[])
    req.getAttribute("javax.servlet.request.X509Certificate")
if (certs != null && certs.length > 0) {
    X509Certificate cert = certs[0];  // the client certificate
    // further processing (extract and compare DN, etc)
}

如果您还没有访问 ServletRequest 的权限,您可以使用 @Context 将其纳入您的服务类的范围:

@javax.ws.rs.core.Context
HttpServletRequest req;

【讨论】:

  • 感谢您的回复。我昨晚在发布之前尝试了这个,但 HttpServletRequest 上下文始终为空,但现在您明确将此确定为解决方案,我做了一些额外的挖掘。见上文。
【解决方案2】:

在泽西邮件列表的帮助下,我能够找到答案。这是正在工作的 RequestFilter 示例:

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.PreMatching;
import javax.ws.rs.ext.Provider;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Provider
@PreMatching
public class SecurityFilter implements ContainerRequestFilter {
    private final Logger log = LoggerFactory.getLogger(getClass());

    @javax.inject.Inject
    private javax.inject.Provider<org.glassfish.grizzly.http.server.Request> request;

    @Override
    public void filter(ContainerRequestContext filterContext) {
        if (request != null) {
            log.debug("User principle: " + request.get().getUserPrincipal().getName());
        }
    }
}

感谢您的帮助!

【讨论】:

    猜你喜欢
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-08
    • 2014-09-05
    • 2011-06-26
    • 2020-10-23
    相关资源
    最近更新 更多