Java 使用客户端的服务器端访问控制';s X509证书DN

Java 使用客户端的服务器端访问控制';s X509证书DN,java,ssl,jersey,grizzly,Java,Ssl,Jersey,Grizzly,人民 我使用JAX-RS和Jersey 2.17以及Grizzly作为我的HTTP服务器。我已配置客户端身份验证并正在工作,但是,我正在尝试对客户端的X.509证书DN实施访问控制。这将为我提供与配置ApacheHTTPD和FakeBasicAuth时相同的功能 我曾尝试使用ContainerRequestFilter,但似乎可以找到一种方法来获取对与TLS会话关联的客户端DN的引用。有人能告诉我一种使用ContainerRequestFilter或任何其他机制访问证书的方法,以实现相同的最终目

人民

我使用JAX-RS和Jersey 2.17以及Grizzly作为我的HTTP服务器。我已配置客户端身份验证并正在工作,但是,我正在尝试对客户端的X.509证书DN实施访问控制。这将为我提供与配置ApacheHTTPD和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”中,是否有其他方法可以访问用户证书

谢谢大家!


John

来自Java Servlet规范:

如果存在与请求关联的SSL证书,则servlet容器必须将其作为
java.security.cert.X509Certificate
类型的对象数组公开给servlet程序员,并通过
javax.servlet.request.X509Certificate的
ServletRequest
属性

此数组的顺序定义为信任的升序。第一 链中的证书是由 客户,下一个 是过去的那个吗 对第一个进行身份验证,依此类推

实际上,这意味着:

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;

根据Java Servlet规范:

如果存在与请求关联的SSL证书,则servlet容器必须将其作为
java.security.cert.X509Certificate
类型的对象数组公开给servlet程序员,并通过
javax.servlet.request.X509Certificate的
ServletRequest
属性

此数组的顺序定义为信任的升序。第一 链中的证书是由 客户,下一个 是过去的那个吗 对第一个进行身份验证,依此类推

实际上,这意味着:

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;

在泽西岛邮件列表的帮助下,我找到了答案。以下是woking 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());
        }
    }
}
import javax.ws.rs.container.ContainerRequestContext;
导入javax.ws.rs.container.ContainerRequestFilter;
导入javax.ws.rs.container.prematch;
导入javax.ws.rs.ext.Provider;
导入org.slf4j.Logger;
导入org.slf4j.LoggerFactory;
@提供者
@预匹配
公共类SecurityFilter实现ContainerRequestFilter{
私有最终记录器log=LoggerFactory.getLogger(getClass());
@javax.inject.inject
私有javax.inject.Provider请求;
@凌驾
公共无效筛选器(ContainerRequestContext筛选器上下文){
if(请求!=null){
调试(“用户原则:+request.get().getUserPrincipal().getName());
}
}
}

谢谢你的帮助

在泽西岛邮件列表的帮助下,我找到了答案。以下是woking 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());
        }
    }
}
import javax.ws.rs.container.ContainerRequestContext;
导入javax.ws.rs.container.ContainerRequestFilter;
导入javax.ws.rs.container.prematch;
导入javax.ws.rs.ext.Provider;
导入org.slf4j.Logger;
导入org.slf4j.LoggerFactory;
@提供者
@预匹配
公共类SecurityFilter实现ContainerRequestFilter{
私有最终记录器log=LoggerFactory.getLogger(getClass());
@javax.inject.inject
私有javax.inject.Provider请求;
@凌驾
公共无效筛选器(ContainerRequestContext筛选器上下文){
if(请求!=null){
调试(“用户原则:+request.get().getUserPrincipal().getName());
}
}
}

谢谢你的帮助

请参阅Servlet规范。客户端证书可通过请求属性获得。请参阅Servlet规范。客户端证书可通过请求属性获得。感谢您的回复。在发布之前,我昨晚尝试了这个方法,但是HttpServletRequest上下文总是空的,但是现在您明确地将其标识为解决方案,我做了一些额外的挖掘。见上文。感谢您的回复。在发布之前,我昨晚尝试了这个方法,但是HttpServletRequest上下文总是空的,但是现在您明确地将其标识为解决方案,我做了一些额外的挖掘。见上文。