【问题标题】:How to avoid adding principal in glassfish-web.xml file when using auth-method=CLIENT-CERT?使用 auth-method=CLIENT-CERT 时如何避免在 glassfish-web.xml 文件中添加主体?
【发布时间】:2014-12-12 10:32:12
【问题描述】:

我刚刚开始为 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 控制对资源的访问仍然是一个有效的问题。但我不急于得到答复。

【问题讨论】:

    标签: java security glassfish glassfish-4.1


    【解决方案1】:

    我遇到了同样的问题并通过此链接解决了它: 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 将是为所有使用有效证书成功登录的用户动态创建的组。

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

    希望对您有所帮助。谢谢!

    【讨论】:

    • 没有。对不起,但它真的没有帮助。它解决了每个人都有一个有效证书被认证的问题,而无需将每个用户添加到 glassfish-web.xml,但不是用户的授权。并非服务器上的所有资源都是 Servlet,因此我不能总是在访问资源时检查证书。
    猜你喜欢
    • 2012-11-19
    • 1970-01-01
    • 2010-09-14
    • 1970-01-01
    • 1970-01-01
    • 2018-09-16
    • 1970-01-01
    • 1970-01-01
    • 2013-04-19
    相关资源
    最近更新 更多