我刚刚开始为Glassfish 4.1编写一个Web应用程序,而且我已经开始使用安全资料。
访问该应用程序的用户将使用客户端证书自行识别它们。我创建了一个自签名的根CA.将此根CA添加到 domain-dir /config/cacerts.jks。创建了一个客户端证书,使用根CA签名并将其添加到我的Web浏览器中。
的web.xml:
<web-app>
<!-- other stuff -->
<security-constraint>
<web-resource-collection>
<web-resource-name>foo</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>operator</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>CLIENT-CERT</auth-method>
</login-config>
<security-role>
<role-name>operator</role-name>
</security-role>
</web-app>
的glassfish-web.xml中:
<glassfish-web-app>
<context-root>/foo</context-root>
<security-role-mapping>
<role-name>operator</role-name>
<principal-name>CN=user</principal-name>
</security-role-mapping>
</glassfish-web-app>
这很有效,但我不想为每个新用户在glassfish-web.xml中添加一个主体名称。我想从数据库中获取该信息以及每个用户的组信息。
我已经调查并试图编写我自己的领域,扩展 com.sun.appserv.security.AppservRealm 。我已经以正确的方式添加了领域,但它只能用于我将web.xml中的auth-method设置为 BASIC 。使用 CLIENT-CERT 将忽略realm-name元素:
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>my-realm</realm-name>
</login-config>
<login-config>
<auth-method>CLIENT-CERT</auth-method>
<realm-name>my-realm</realm-name>
</login-config>
在第二种情况下,预先定义的领域证书&#39;将会被使用。使用 BASIC 显然不会使用客户端证书。
还有另一种方法,那就是修改 domain-dir /config/domain.xml并替换
...
<config name="server-config">
...
<security-service>
...
<auth-realm classname="com.sun.enterprise.security.auth.realm.certificate.CertificateRealm" name="certificate"></auth-realm>
与
...
<config name="server-config">
...
<security-service>
...
<auth-realm classname="org.foo.MyCertificateRealm" name="certificate"></auth-realm>
但这也无济于事。我在日志中收到以下警告:&#34;证书身份验证需要证书领域。&#34;谷歌搜索告诉我,使用的领域必须是CertificateRealm的一个实例,我认为它意味着 com.sun.enterprise.security.auth.realm.certificate.CertificateRealm ,但那个类是最终的,所以我无法延长它。
除了glassfish-web.xml之外,是否无法将您的主体及其组定义在其他地方?我应该抛弃Glassfish并使用其他东西,比如JBoss吗?
编辑2015-03-31:
在问这个问题后不久,我尝试了Jetty,在那里我设法做了我想做的事情。我甚至能够将CLIENT-CERT身份验证与FORM身份验证结合起来,如果客户端没有提供有效证书,则会将用户重定向到基于表单的登录页面,并且可以使用用户名和密码。
然后在身份验证时将角色添加到用户,以便Jetty可以控制对资源的访问。
如果可以在CLIENT-CERT模式下控制Glassfish中用户的角色分配,而无需将每个用户添加到glassfish-web.xml,但是能够从例如一个数据库,并允许Glassfish控制对资源的访问仍然是一个有效的问题。但我并不急于得到答案。
答案 0 :(得分:0)
我遇到了同样的问题并通过以下链接解决了问题: here
只需使用domain.xml文件中的属性assign-groups:
<auth-realm classname="com.sun.enterprise.security.auth.realm.certificate.CertificateRealm" name="certificate">
<property name="assign-groups" value="allusers"></property>
</auth-realm>
allusers将是为使用有效证书成功登录的所有用户动态创建的组。
将主标记和值替换为group-name标记,将值替换为allusers。所以你必须像这样修改你的glassfish-web.xml:
<glassfish-web-app>
<context-root>/foo</context-root>
<security-role-mapping>
<role-name>operator</role-name>
<group-name>allusers</group-name>
</security-role-mapping>
</glassfish-web-app>
无需在web.xml中添加Principals。您可以在检查Servlet后通过以下方式检查连接证书:
X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
并使用以下内容检查DN部分:
String dn = certs[0].getSubjectX500Principal().getName();
希望它有所帮助。谢谢!