"CLIENT-CERT" Grails 3.3 中基于 X509 证书的身份验证
"CLIENT-CERT" based X509 certificate authentication in Grails 3.3
一段时间以来,在尝试升级到 Grails 3 时,我一直在尝试镜像我在 Grails 2 中的实现。
我需要使用 "client-cert" 身份验证方法支持基于 X509 证书的身份验证,也就是说,我只想在请求受保护资源后提示我输入证书。
请参阅下面 Application.groovy.
中的当前实施
@Bean
EmbeddedServletContainerCustomizer containerCustomizer() throws Exception {
return new EmbeddedServletContainerCustomizer() {
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
TomcatEmbeddedServletContainerFactory tomcat = (TomcatEmbeddedServletContainerFactory) container
tomcat.addConnectorCustomizers(
new TomcatConnectorCustomizer() {
@Override
public void customize(Connector connector) {
connector.setPort(8443)
connector.setSecure(true)
connector.setScheme("https")
Http11NioProtocol proto = (Http11NioProtocol) connector.getProtocolHandler()
proto.setMinSpareThreads(5)
proto.setSSLEnabled(true)
proto.setClientAuth("false")
proto.setKeystoreFile("/tmp/keys/app.jks")
proto.setKeystorePass("changeit")
proto.setKeystoreType("JKS")
proto.setKeyAlias("ssl_server")
proto.setTruststoreFile("/tmp/keys/app.jts")
proto.setTruststoreType("JKS")
proto.setTruststorePass("changeit")
}
})
tomcat.addContextCustomizers(new TomcatContextCustomizer() {
@Override
public void customize(Context context) {
context.setPath("/myapp")
SecurityConstraint sc = new SecurityConstraint()
SecurityCollection securityCollection = new SecurityCollection()
securityCollection.setName("Protected")
securityCollection.addPattern("/*")
sc.addCollection(securityCollection)
sc.addAuthRole("mySecureConnection")
sc.setUserConstraint("CONFIDENTIAL")
context.addConstraint(sc)
context.addSecurityRole("mySecureConnection")
context.setRealm(new MySecurityRealm())
LoginConfig loginConfig = new LoginConfig()
loginConfig.setAuthMethod("CLIENT-CERT")
loginConfig.setRealmName("MySecurityRealm")
context.setLoginConfig(loginConfig)
sc.setAuthConstraint(true)
}
});
}
}
但是无论我尝试使用多少种不同的方式来剪切它,应用程序都不会在访问时请求证书(它应该基于我上面的捕获所有模式)。
请注意,当 clientAuth 设置为 true;
时,此机制确实会按预期工作
proto.setClientAuth("true")
但这意味着总是需要一个证书,这不是我最终想要的(我打算更新上面的模式)。
任何帮助将不胜感激。
在回到 Grails 3 之前,在香草 tomcat 和 Spring 引导级别进行概念验证后,我自己就开始工作了。3.x 应用有效的方法。
我认为拼图中最重要的部分可能是添加了一个 tomcat 阀组件(显然使用 SSLAuthenticator 实现),这是我设法让浏览器提示输入证书的唯一方法。然后,这要求我使用自定义领域从证书中检索主体(目前我不知道其他方法)。
代码如下;
@Bean
public EmbeddedServletContainerFactory servletContainer() {
final TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
tomcat.addContextValves(new SSLAuthenticator());
tomcat.addContextCustomizers(new TomcatContextCustomizer() {
@Override
public void customize(Context ctx) {
String AUTH_ROLE = "mySecureRole";
ctx.addSecurityRole(AUTH_ROLE);
ctx.setRealm(new MySecurityRealm())
LoginConfig config = new LoginConfig();
config.setAuthMethod("CLIENT-CERT");
config.setRealmName("MySecurityRealm");
ctx.setLoginConfig(config);
SecurityConstraint constraint = new SecurityConstraint();
constraint.addAuthRole(AUTH_ROLE);
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/secure");
constraint.addCollection(collection);
ctx.addConstraint(constraint);
}
})
tomcat.addAdditionalTomcatConnectors(createConnector());
return tomcat;
}
private Connector createConnector() {
Connector connector = new Connector(TomcatEmbeddedServletContainerFactory.DEFAULT_PROTOCOL);
connector.setPort(8443);
connector.setSecure(true);
connector.setScheme("https");
Http11NioProtocol proto = (Http11NioProtocol) connector.getProtocolHandler();
proto.setMinSpareThreads(5);
proto.setSSLEnabled(true);
proto.setClientAuth("false");
proto.setSSLProtocol("all");
proto.setKeystoreFile("/path/store.jks");
proto.setKeystorePass("changeit");
proto.setKeystoreType("JKS");
proto.setKeyAlias("ssl_server");
proto.setTruststoreFile("/path/store.jts");
proto.setTruststoreType("JKS");
proto.setTruststorePass("changeit");
proto.setSSLVerifyDepth(2);
return connector;
}
为了完整起见,我将保留连接器的详细信息,但当然,所有重要的事情都发生在上下文定制器中。
现在,当我访问此 Web 应用程序时,系统不会提示我提供证书。这仅在我访问 /secure 路径时发生,这正是我所需要的。
一段时间以来,在尝试升级到 Grails 3 时,我一直在尝试镜像我在 Grails 2 中的实现。
我需要使用 "client-cert" 身份验证方法支持基于 X509 证书的身份验证,也就是说,我只想在请求受保护资源后提示我输入证书。 请参阅下面 Application.groovy.
中的当前实施@Bean
EmbeddedServletContainerCustomizer containerCustomizer() throws Exception {
return new EmbeddedServletContainerCustomizer() {
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
TomcatEmbeddedServletContainerFactory tomcat = (TomcatEmbeddedServletContainerFactory) container
tomcat.addConnectorCustomizers(
new TomcatConnectorCustomizer() {
@Override
public void customize(Connector connector) {
connector.setPort(8443)
connector.setSecure(true)
connector.setScheme("https")
Http11NioProtocol proto = (Http11NioProtocol) connector.getProtocolHandler()
proto.setMinSpareThreads(5)
proto.setSSLEnabled(true)
proto.setClientAuth("false")
proto.setKeystoreFile("/tmp/keys/app.jks")
proto.setKeystorePass("changeit")
proto.setKeystoreType("JKS")
proto.setKeyAlias("ssl_server")
proto.setTruststoreFile("/tmp/keys/app.jts")
proto.setTruststoreType("JKS")
proto.setTruststorePass("changeit")
}
})
tomcat.addContextCustomizers(new TomcatContextCustomizer() {
@Override
public void customize(Context context) {
context.setPath("/myapp")
SecurityConstraint sc = new SecurityConstraint()
SecurityCollection securityCollection = new SecurityCollection()
securityCollection.setName("Protected")
securityCollection.addPattern("/*")
sc.addCollection(securityCollection)
sc.addAuthRole("mySecureConnection")
sc.setUserConstraint("CONFIDENTIAL")
context.addConstraint(sc)
context.addSecurityRole("mySecureConnection")
context.setRealm(new MySecurityRealm())
LoginConfig loginConfig = new LoginConfig()
loginConfig.setAuthMethod("CLIENT-CERT")
loginConfig.setRealmName("MySecurityRealm")
context.setLoginConfig(loginConfig)
sc.setAuthConstraint(true)
}
});
}
}
但是无论我尝试使用多少种不同的方式来剪切它,应用程序都不会在访问时请求证书(它应该基于我上面的捕获所有模式)。 请注意,当 clientAuth 设置为 true;
时,此机制确实会按预期工作proto.setClientAuth("true")
但这意味着总是需要一个证书,这不是我最终想要的(我打算更新上面的模式)。 任何帮助将不胜感激。
在回到 Grails 3 之前,在香草 tomcat 和 Spring 引导级别进行概念验证后,我自己就开始工作了。3.x 应用有效的方法。 我认为拼图中最重要的部分可能是添加了一个 tomcat 阀组件(显然使用 SSLAuthenticator 实现),这是我设法让浏览器提示输入证书的唯一方法。然后,这要求我使用自定义领域从证书中检索主体(目前我不知道其他方法)。 代码如下;
@Bean
public EmbeddedServletContainerFactory servletContainer() {
final TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
tomcat.addContextValves(new SSLAuthenticator());
tomcat.addContextCustomizers(new TomcatContextCustomizer() {
@Override
public void customize(Context ctx) {
String AUTH_ROLE = "mySecureRole";
ctx.addSecurityRole(AUTH_ROLE);
ctx.setRealm(new MySecurityRealm())
LoginConfig config = new LoginConfig();
config.setAuthMethod("CLIENT-CERT");
config.setRealmName("MySecurityRealm");
ctx.setLoginConfig(config);
SecurityConstraint constraint = new SecurityConstraint();
constraint.addAuthRole(AUTH_ROLE);
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/secure");
constraint.addCollection(collection);
ctx.addConstraint(constraint);
}
})
tomcat.addAdditionalTomcatConnectors(createConnector());
return tomcat;
}
private Connector createConnector() {
Connector connector = new Connector(TomcatEmbeddedServletContainerFactory.DEFAULT_PROTOCOL);
connector.setPort(8443);
connector.setSecure(true);
connector.setScheme("https");
Http11NioProtocol proto = (Http11NioProtocol) connector.getProtocolHandler();
proto.setMinSpareThreads(5);
proto.setSSLEnabled(true);
proto.setClientAuth("false");
proto.setSSLProtocol("all");
proto.setKeystoreFile("/path/store.jks");
proto.setKeystorePass("changeit");
proto.setKeystoreType("JKS");
proto.setKeyAlias("ssl_server");
proto.setTruststoreFile("/path/store.jts");
proto.setTruststoreType("JKS");
proto.setTruststorePass("changeit");
proto.setSSLVerifyDepth(2);
return connector;
}
为了完整起见,我将保留连接器的详细信息,但当然,所有重要的事情都发生在上下文定制器中。 现在,当我访问此 Web 应用程序时,系统不会提示我提供证书。这仅在我访问 /secure 路径时发生,这正是我所需要的。