Nginx地图客户端证书REMOTE_USER为uWSGI回退到基本身份validation?

我使用nginx和uWSGI来为Mercurial服务; 它通过SSL进行基本身份validation(Nginx是SSL终结者;它不会传递给Hg),但是由于基本身份validation(即使通过SSL)的安全性有限,正如包括本站在内的各个地方所讨论的,我想允许用户也可以连接客户端证书,例如TortoiseHg支持的东西。

ssl_verify_client optional; ... map $ssl_client_s_dn $ssl_client_s_dn_cn { default ""; ~/CN=(?<CN>[^/]+) $CN; }; ... location / { uwsgi_pass unix:/run/uwsgi/app/hgweb/socket; include uwsgi_params; uwsgi_param SERVER_ADDR $server_addr; uwsgi_param REMOTE_USER $ssl_client_s_dn_cn; #uwsgi_param REMOTE_USER $remote_user; #auth_basic "Mercurial repositories"; #auth_basic_user_file /srv/hg/.htpasswd; 

}

所以我把CN当作用户名。 但是,如果没有客户端证书(最好不是在有证书但validation失败时 – 只是在这种情况下出现错误),如何使其回退到基本身份validation? 我发现一个例子是通过一个单独的服务器监听另一个端口,我想避免它: https : //github.com/winne27/nginx-cert-and-basic-auth/blob/master/nginx-example .conf文件

此外,在一些例子中,我已经看到了以下location检查: 他们有必要吗? if ($ssl_client_verify != SUCCESS) { return 496; } if ($ssl_client_verify != SUCCESS) { return 496; } if ($ssl_client_s_dn_cn !~ "^[a-z0-9]{1,10}$") { return 496; } 鉴于http://wiki.nginx.org/IfIsEvil我认为最好避免使用if

我看到两种可能的解决方案,可以覆盖uwsgi_param或使用$remote_user作为变量$ssl_client_s_dn_cn的默认值。


要覆盖uwsgi_param (这应该也适用于fastcgi_param ),请按照您的建议使用map指令(只需在“}”)之后移除“;”,并为该指令使用if_not_empty参数:

 uwsgi_param REMOTE_USER $remote_user; uwsgi_param REMOTE_USER $ssl_client_s_dn_cn if_not_empty; 

$ssl_client_s_dn_cn应该覆盖$remote_user如果存在)。 这种方法的优点是在别处分别使用两个不同的变量名称(例如日志格式)。

请参阅: http : //nginx.org/en/docs/http/ngx_http_uwsgi_module.html#uwsgi_param


要在定义map时使用$remote_user作为$ssl_client_s_dn_cn变量的默认值:

 map $ssl_client_s_dn $ssl_client_s_dn_cn { default $remote_user; ~/CN=(?<CN>[^/]+) $CN; } 

请注意, map指令不能在server上下文中使用,而location应该。 还要注意,Nginx变量不能被覆盖。

Nginx 1.11和1.12改变了$ ssl_client_s_dn_cn的引用。

如果你来这里头痛,试试这个正则表达式:

 map $ssl_client_s_dn $ssl_client_s_dn_cn { default "should_not_happen"; ~CN=(?<CN>[^/,\"]+) $CN; }