使用 Nginx 和 Tomcat 网络应用程序的 TLS 客户端身份验证

TLS client authentication with Nginx and Tomcat web application

我有一个 Tomcat 8 网络应用程序,它在服务器的端口 8080 上运行。任何对端口 443 的传入请求都将转发到 localhost:8080,使用 Nginx 为 Web 应用程序提供服务。

我正在尝试设置相互身份验证,然后解析应用程序用于身份验证的客户端证书。然后应用程序将使用此信息来决定用户是否应具有 adminuser 权限。客户端证书将在通用名称 (CN) 字段中包含字符串 adminuser

我能够实现相互认证 & 下面是当前的 nginx ssl.conf 但是问题是证书信息没有传递给 tomcat web 应用程序来解析数据。 nginx 中是否有一种方法可以传递客户端证书数据,以便 tomcat8 应用程序可以使用它?

server {
    listen       443 default_server;
    server_name  name.domain.com;

    ssl on;
    ssl_certificate /etc/nginx/self-signed.pem;
    ssl_certificate_key /etc/nginx/self-signed.pem;
    ssl_protocols SSLv2 TLSv1 TLSv1.1 TLSv1.2;


    ssl_client_certificate /etc/nginx/ca.cert.pem;
    ssl_verify_client optional;
    ssl_verify_depth  2;
    ssl_session_timeout  5m;
    ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
    ssl_prefer_server_ciphers  on;


    port_in_redirect off;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    #test page for the load balancer
    location /loadbalancer {
      add_header X-Frame-Options "DENY";
      auth_basic off;
      #proxy_pass http://localhost:8080;
      try_files $uri /test.html;
    }

    location /webapi {
      add_header X-Frame-Options "DENY";
      auth_basic off;
      proxy_pass http://localhost:8080;
    }

    location / {
      if ($ssl_client_verify != SUCCESS)

     {
      return 403;
      break;
     }

      add_header X-Frame-Options "DENY";
      proxy_pass http://localhost:8080;
    }


    error_page  404              /404.html;
      location = /404.html {
      root   /usr/share/nginx/html;
    }

    error_page   500 502 503 504  /50x.html;
      location = /50x.html {
      root   /usr/share/nginx/html;
    }
}

您可以使用 proxy_set_header 指令将额外的 headers 传递给您的 tomcat。

可用变量

http://nginx.org/en/docs/http/ngx_http_ssl_module.html#var_ssl_cipher

示例

proxy_set_header SSL_DN $ssl_client_s_dn;

在您的 Java 应用中,您可以阅读此 headers 以进行进一步处理。

附带说明一下,我不会将访问级别保存在证书中,而是保存在服务器端数据库中,这样您可以更轻松地重新分配/更改/添加角色 或撤销有效证书。

编辑 实际上 nginx 也支持证书撤销列表: http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_crl

关于 nginx 的好文章 + php 可以很容易地适应您的用例:

http://nategood.com/client-side-certificate-authentication-in-ngi