人民,
我使用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上下文始终为null。我正在使用GrizzlyHttpServerFactory,如下所示:GrizzlyHttpServerFactory.createHttpServer(
getServerURI(), getResourceConfig(), true,
new SSLEngineConfigurator(sslContext.get())
.setNeedClientAuth(true).setClientMode(false))
相信不是servlet容器,因此不支持HttpServletRequest上下文。我很快就看到了GrizzlyWebContainerFactory,但初始化完全不同,并希望避免这种痛苦。是否有其他方法可以访问" javax.ws.rs.container.ContainerRequestFilter"中的用户证书?
谢谢!
约翰
答案 0 :(得分:3)
来自Java Servlet规范:
如果存在与请求关联的SSL证书,则servlet容器必须将其作为
java.security.cert.X509Certificate
类型的对象数组公开给servlet程序员,并且可以通过ServletRequest
的{{1}}属性。此数组的顺序定义为信任的升序。首先 链中的证书是由...设置的 客户,下一个 是以前的人 验证第一个,依此类推。
实际上,这意味着:
javax.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
答案 1 :(得分:1)
在Jersey邮件列表的帮助下,我得出了答案。这是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());
}
}
}
感谢您的帮助!