在Tomcat中使用CLIENT-CERT而不指定用户名

12

我正在试图让Tomcat Web应用程序对传入连接使用客户端证书认证。当在server.xml中使用clientAuth=true时,一切都正常,但由于在同一服务器上运行其他应用程序,我们无法在生产环境中使用它。

是否有一种方法可以形成一个web.xml文档,以使其强制要求应用程序使用与clientAuth=true相同的客户端证书?似乎使用CLIENT-CERT设置还需要为每个证书设置一个Tomcat用户帐户才能访问您的系统?我们需要能够允许所有来自特定CA(设置在服务器信任商店中)且主题符合某些规则(在实际应用程序中进行检查)的证书。我希望像以下示例一样,但目前还没有成功!

<security-constraint>
    <web-resource-collection>
        <web-resource-name>Everything</web-resource-name>
        <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <user-data-constraint>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
</security-constraint>
<login-config>
    <auth-method>CLIENT-CERT</auth-method>
</login-config>
2个回答

7
首先,你似乎想要的是clientAuth=want,而不是clientAuth=true:这将允许客户端提供证书,但不一定需要证书。
当您使用任何形式的身份验证时,Tomcat(或任何servlet容器)必须能够构建出一个Principal对象--一个具有名称(通常是用户名)的对象。然后容器必须决定用户在特定请求中拥有的角色以便正确的授权。因此,在进行授权之前,Tomcat需要预先了解这些用户信息。
另一方面,如果您不需要任何授权,可以设置clientAuth=want,然后使用Filter来验证证书。如果您已经在自己进行检查,则无需使用CLIENT-CERT身份验证。

1
在连接器配置中,clientAuth=false,而在web.xml中使用CLIENT-CERT可以让您获取客户端证书以进行重新协商,这很方便,如果您不想/不需要其他Web应用程序在浏览器中引起提示。 - Bruno
1
这就是我之前尝试的,但看起来我可能误解了这里CLIENT-CERT选项的用法。那么,web.xml中的CLIENT-CERT仅仅是用于使用证书作为特定用户进行身份验证?到目前为止,我的大部分经验都是在IIS上,我希望Tomcat能够以相同的方式工作,即您可以指定整个服务器、单个项目甚至单个页面在连接被允许前需要提供有效的客户端证书。 - user unknown
@Christopher-Schultz:我曾尝试过clientAuth=want,它确实有效,但我不确定它是否安全。然而,再考虑一下——如果没有证书被呈现,我们的代码仍将处理并拒绝它们。如果他们提供了客户端证书,那么它可能必须经过Tomcat在clientAuth=true时进行的所有检查(例如受信任的CA、有效期在范围内等),然后才能传递给我们的代码进行进一步验证,因此它将完全相同地工作? - user unknown
1
如果您的 Web 应用程序需要 CLIENT-CERT 认证,则 Web 应用程序本身将要求提供证书以访问受保护的资源。clientAuth=want 只是防止 <Connector>所有 请求都要求证书。如果启用 Tomcat 的证书验证,则仅在存在证书时才执行验证,否则将跳过验证。我认为您会对我所提供的配置感到满意。 - Christopher Schultz
1
我忘了提到:要信任由CA签名的所有证书,您只需正确配置您的信任存储。 - Christopher Schultz

5

我刚刚在寻找解决上述问题的方案,最终找到了一个解决方案:

  1. Configure tomcat with connector clientAuth="false" attribute(Otherwise all secure connections to server will do mutual, client server, ssl authentification.

  2. Add the following in web.xml(I have just shown here example)

    <security-constraint>
        <web-resource-collection>
            <url-pattern>/LoginTestServlet1</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>manager</role-name>
        </auth-constraint>
        <user-data-constraint>
            <!-- transport-guarantee can be CONFIDENTIAL, INTEGRAL, or NONE -->
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>
     <security-constraint>
        <web-resource-collection>
            <url-pattern>/LoginTestServlet2</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>manager</role-name>
        </auth-constraint>
       <!--  <user-data-constraint>
            transport-guarantee can be CONFIDENTIAL, INTEGRAL, or NONE
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>  
        </user-data-constraint> -->
    </security-constraint>
     <login-config>
        <auth-method>CLIENT-CERT</auth-method>
        <realm-name>certificate</realm-name>
      </login-config>
    

    manager

  3. In tomcat users-users.xml add the following(pls note that if trust store has almost identical certificates then you should clearly identify your certificate as follows)

    <role rolename="manager"/>
    

    < user username="EMAILADDRESS=hamzas100@yahoo.com, CN=KS, OU=OFF, O=OFS, L=Bukhara,
    ST=Bukhara, C=UZ" password="" roles="manager"/>

  4. put in a browser(or curl) address line:

    https://yourdomain.com:8443/LoginTest/LoginTestServlet1 or
    https://yourdomain.com:8443/LoginTest/LoginTestServlet2

  5. For this to work you have to add certificate to browser personal certificate list(if you are testing with browser). I have tried with Mozilla Firefox and it will easyly let you do this.(But it only accepts b12 certificate so it is suggested that you should use openssl with java keytool). If everything configured right then you will get prompt from mozilla to choose certificate from existing ones. If you are using curl(it is used for automatic web interfaces testing then use the following commant line to test(I have just given an example here.) Plese note that you should choose certificate which you imported into trust store.

    curl -s -k --cert selfsigned.pem --key key.pem -v --anyauth https://yourdomain.com:8443/LoginTest/LoginTestServlet1 --cacert selfsigned.pem or curl -s -k --cert selfsigned.pem --key key.pem -v --anyauth http://yourdomain.com:8080/LoginTest/LoginTestServlet2 --cacert selfsigned.pem

注意:我的连接器如下所示:
<Connector port="8443"
       maxThreads="150"  scheme="https" secure="true" SSLEnabled="true"
       sslProtocol="TLS" keystoreType="PKCS12"  truststoreType="PKCS12" clientAuth="false"
               keystoreFile="C:/Program Files/glassfish-3.1.2/glassfish/domains/domain1/config/cacerts.pkcs12"
               truststoreFile= "C:/Program Files/glassfish-3.1.2/glassfish/domains/domain1/config/cacerts.pkcs12"
               truststorePass="changeit"
               keystorePass="changeit"
               protocol="org.apache.coyote.http11.Http11Protocol">

我已经在Tomcat 6.0.35上进行了测试,但是对于Glassfish,需要对glassfish-web.xml文件进行一些更改,就可以正常工作。 - Khurshed Salimov
<security-role-mapping> <role-name>manager</role-name> <principal-name>EMAILADDRESS=hamzas100@yahoo.com, CN=KS,OU=OFF,O=OFS,L=Bukhara,S=Bukhara,C=UZ</principal-name> <group-name>manager</group-name> </security-role-mapping> - Khurshed Salimov
有些证书很容易添加到浏览器的个人存储中,例如pkcs12证书。要将它们添加到Crome/Cromium和Internet Explorer浏览器(新版本)的个人证书存储中,只需双击它们并按照向导中的步骤进行操作即可。对于其他浏览器,如Mozilla Firefox v21,您需要在浏览器上手动完成此操作。 - Khurshed Salimov
关于 Opera 的情况与 Mozilla 相同,需要添加客户端证书认证的证书。 - Khurshed Salimov
所有浏览器都支持多个证书。 - Khurshed Salimov
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接