在不指定用户名的情况下使用 Tomcat 的 CLIENT-CERT

Posted

技术标签:

【中文标题】在不指定用户名的情况下使用 Tomcat 的 CLIENT-CERT【英文标题】:Using CLIENT-CERT for Tomcat without specifying a username 【发布时间】:2012-07-30 10:24:05 【问题描述】:

我正在尝试使 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>

【问题讨论】:

【参考方案1】:

首先,听起来您想要clientAuth=want 而不是clientAuth=true:这将允许客户端提供证书,但并非绝对需要。

当您使用任何类型的身份验证时,Tomcat(或任何 servlet 容器)必须能够从中构建一个 Principal 对象——一个具有名称(通常是用户名)的对象。然后容器必须决定用户拥有什么角色才能正确授权特定请求。因此,Tomcat 需要事先了解用户才能进行授权。

另一方面,如果您不需要任何授权,您可以设置clientAuth=want,然后使用Filter 来验证证书。如果您已经在进行自己的检查,则无需使用CLIENT-CERT 身份验证。

【讨论】:

连接器配置中的 clientAuth=falseweb.xml 中的 CLIENT-CERT 允许您获取客户端证书以进行重新协商,如果您不想/不需要其他 web 应用程序,这很方便在浏览器中引起提示。 这就是我在上面尝试做的,但看起来我可能误解了这里 CLIENT-CERT 选项的用法。那么,web.xml 中的 CLIENT-CERT 用于使用证书作为特定用户进行身份验证?到目前为止,我的大部分经验都是使用 IIS,我希望 Tomcat 也能以同样的方式工作,您可以在其中指定整个服务器、单个项目甚至单个页面是否需要在连接之前提供有效的客户端证书允许。 @Christopher-Schultz:我尝试过 clientAuth=want,它确实有效,但我不确定它是否同样安全。然而,再想一想——如果没有提供证书,我们的代码无论如何都会解决这个问题并拒绝它们。如果他们确实提供了客户端证书,那么它可能必须经过 Tomcat 在 clientAuth=true 时所做的所有检查(例如,受信任的 CA、范围内的有效性等),然后才能传递给我们的代码以进行进一步验证,因此它将工作完全一样? 如果你的 webapp 需要CLIENT-CERT 身份验证,那么 webapp 本身将需要一个证书来访问受保护的资源。 clientAuth=want 只是阻止 &lt;Connector&gt;all 请求要求证书。如果启用 Tomcat 的证书验证,如果证书存在,则将执行验证,如果不存在则跳过。我认为您对我提供的配置会很好。 我忘了说:要信任所有由 CA 签名的证书,您只需正确配置您的信任库。【参考方案2】:

我只是在研究上述问题的解决方案,终于找到了解决方案:

    使用连接器 clientAuth="false" 属性配置 tomcat(否则所有与服务器的安全连接都将进行相互、客户端服务器、ssl 身份验证。

    在 web.xml 中添加以下内容(我刚刚在这里展示了示例)

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

    经理

    在 tomcat users-users.xml 中添加以下内容(请注意,如果信任库具有几乎相同的证书,那么您应该清楚地标识您的证书,如下所示)

    <role rolename="manager"/>
    

    ST=Bukhara, C=UZ" password="" roles="manager"/>

    放入浏览器(或 curl)地址行:

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

    为此,您必须将证书添加到浏览器个人证书列表(如果您正在使用浏览器进行测试)。我已经尝试使用 Mozilla Firefox,它很容易让你这样做。(但它只接受 b12 证书,所以建议你应该使用带有 java keytool 的 openssl)。如果一切配置正确,那么您将收到 Mozilla 的提示以从现有证书中选择证书。如果您使用 curl(它用于自动 Web 界面测试,则使用以下命令行进行测试(我刚刚在这里给出了一个示例。)请注意,您应该选择导入到信任库中的证书。

    curl -s -k --cert selfsigned.pem --key key.pem -v --anyauth https://yourdomain.com:8443/LoginTest/LoginTestServlet1 --cacert selfsigned.pem 或 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 文件进行一些更改 managerEMAILADDRESS=hamzas100@yahoo.com, CN=KS,OU=OFF,O= OFS,L=Bukhara,S=Bukhara,C=UZmanager 一些证书很容易添加到浏览器个人存储中,例如 pkcs12 证书。要让他们添加到 Crome/Cromium 和 Internet Explorer 浏览器(新版本)的个人证书存储,只需双击它们并按照向导中的步骤操作。对于 Mozilla Firefox v 21 等其他用户,您必须在浏览器上手动完成。 Opera 的情况与 Mozilla 相同,为客户端证书认证添加证书 所有浏览器都支持多个证书

以上是关于在不指定用户名的情况下使用 Tomcat 的 CLIENT-CERT的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在不使用ajax请求的情况下检查用户是否在线?

tomcat绑定域名,在不修改端口号为80的情况下,如何隐藏端口

如何在不指定数据库名称的情况下连接到 PostgreSQL?

如何在不为 Java Bridge 添加 tomcat 服务器的情况下将 Java 后端添加到现有 PHP 站点?

DDS QoS:是不是可以在不指定密钥的情况下发送数据?

如何在不指定方案的情况下使用 UriBuilder 构建 URI,单独托管?