使用Nginx和Tomcat Web应用程序进行TLS客户端身份验证

使用Nginx和Tomcat Web应用程序进行TLS客户端身份验证

问题描述:

我有一个Tomcat 8 Web应用程序,它在服务器上的端口8080上运行。任何到端口443的传入请求都会使用Nginx转发到localhost:8080以提供Web应用程序。使用Nginx和Tomcat Web应用程序进行TLS客户端身份验证

我试图建立相互认证&然后解析用于应用程序认证的客户端证书。这些信息将被应用程序用来决定用户是否应具有adminuser权限。客户证书将在通用名称(CN)字段中携带字符串adminuser

我能够实现相互认证&下面是当前的nginx ssl.conf但是问题在于cert信息没有传递给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指令传递额外头到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应用程序,你可以阅读这个标题作进一步处理。

在旁注中,我不会保存证书中的访问级别,但会保存在服务器端数据库中,这样您可以更轻松地重新分配/更改/添加角色或撤销有效证书。

编辑 事实上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

+0

这' proxy_set_header SSL_DN $ ssl_client_s_dn;'确实有效!谢谢。 – OK999

+1

请注意,如果您需要完整证书,则有两个变量:'ssl_client_cert',其中Nginx将用制表符替换'\ n';和'ssl_client_raw_cert',它有新的行,但会破坏你的HTTP连接。 使用[官方Tomcat SSL阀](https://tomcat.apache.org/tomcat-8.0-doc/api/org/apache/catalina/valves/SSLValve.html)不起作用(仅替换withspaces和而不是标签) – lucasvc

+0

而对于ssl_client_cert官方的Nginx文档似乎没有提到“\ n”被替换。只提到“\ t”是前置的(但\ n实际上被替换):http://nginx.org/en/docs/http/ngx_http_ssl_module.html – Khanna111