1

我刚刚开始为 Glassfish 4.1 编写一个 Web 应用程序,并且开始处理安全问题。

访问应用程序的用户将使用客户端证书来识别他们自己。我创建了一个自签名的根 CA。将此根 CA 添加到domain-dir /config/cacerts.jks。创建客户端证书,使用根 CA 对其进行签名并将其添加到我的 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将忽略领域名称元素:

<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>

在第二种情况下,将使用预定义的领域“证书”。并且使用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>

但这也无济于事。我在日志中收到以下警告:“证书身份验证需要证书领域。” 谷歌搜索告诉我,使用的领域必须是 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控制对资源的访问仍然是一个有效的问题。但我并不急于得到答复。

4

1 回答 1

0

我遇到了同样的问题并通过此链接解决: 这里

只需像这样使用 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 将是为所有使用有效证书成功登录的用户动态创建的组。

将主体标记和值替换为组名称标记和值作为 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();

希望它有帮助。谢谢!

于 2015-03-30T17:28:11.937 回答