Kri*_*aig 15 php linux apache ssl openssl
首先,请注意我是配置SSL的新手.在过去,我总是很幸运有一个IT部门可以提前为我做好准备.因此,请准备好我可能需要澄清你的一些答案.=)
我正在尝试做什么
我正在为员工建立一个公司内联网网站.例如,将有一个浏览器起始页面,显示为每个员工定制的内容.因此,我需要能够识别所述员工而无需任何用户名/密码或其他提示(虽然一次性设置是可以的;我只是不希望每次都提示他们).当然,SSL似乎是实现这一目标的最佳方式.
我将使用MySQL数据库设置将"用户"帐户与SSL_CLIENT_M_SERIAL和SSL_CLIENT_I_DN相关联,我假设每个客户端证书(?)都是唯一的.我从这篇文章中得到了这个想法:http: //cweiske.de/tagebuch/ssl-client-certificates.htm
用户第一次访问内部网站时,他们将没有证书(我不想为客户手动生成证书!),在这种情况下$ _SERVER ["SSL_CLIENT_VERIFY"] =="NONE".如果发生这种情况,它将转到用户帐户设置页面,其中包括PHP生成SSL客户端证书并将其发送到浏览器以供用户安装的步骤.很好,很简单.然后,用户安装证书,建立关联,并在重新启动浏览器后(为了更好地衡量),用户返回内部网站.
此时,Apache应该请求客户端证书,然后浏览器发送该证书.PHP脚本然后解析必要的$ _SERVER变量,与MySQL数据库进行比较,并且所有人都有好的时间.再次,好又简单.
什么工作到目前为止
我安装了服务器端证书.是的,他们是自签名的(出于显而易见的原因).Apache安装了mod_ssl,所有这些似乎都运行正常.我创建了一个只转储$ _SERVER数组的PHP脚本,所有SSL_SERVER_*键值都与我为它创建的证书相匹配.
问题
我无法获得客户端证书!在同一个PHP脚本中,无论我做什么,都缺少SSL_CLIENT_VERIFY =="NONE"和其他SSL_CLIENT_*键.如果我在ssl.conf中将SSLVerifyClient设置为可选,则会发生这种情况.根据我读过的每个教程,他们都说网络服务器应该向浏览器询问客户端证书.事情是,我无法做到这一点!它只是直接进入PHP脚本,并假设我根本没有客户端证书.这种情况发生在Firefox,Chrome和IE中.
所以我尝试将SSLVerifyClient设置为必需并重新启动Web服务器.有了这个选项,我甚至无法建立SSL连接.Firefox只是说连接已经重置(其他浏览器也会显示自己的错误版本).奇怪的是,日志在这些连接尝试中没有显示任何活动!即access_log,error_log,ssl_access_log,ssl_error_log和ssl_request_log都不显示任何内容 ; 就好像这次尝试从未发生过一样.这令人沮丧,因为这意味着我甚至没有可以使用的错误消息.只是一个网络服务器被动 - 积极地告诉我下地狱.
我尝试使用PHP的OpenSSL扩展手动生成/安装我自己的客户端证书.证书安装得很好,虽然我找不到任何关于如何将该证书与服务器关联的信息(假设我甚至需要?).此外,它似乎无关紧要,因为如果设置了可选项,Apache仍然不会请求客户端证书.如果设置了需求,它只是在没有解释的情况下爆炸.无论如何,我需要将它设置为可选,以使此模式起作用.
环境
操作系统:CentOS 5.7 64位(VirtualBox)
Apache:2.2.3
PHP:5.3.10
我猜你可能需要更多的信息来帮助我,所以请问!我会为你提供你需要的一切.
总而言之,我需要知道如何在给定上述条件的情况下让Apache请求SSL客户端证书.此外,如果有任何特殊的签名/等必须要使客户端证书与服务器证书"兼容"(再次,没有通过shell为每个客户端证书手动执行!),我将需要知道好.
到目前为止,我100%坚持这一点.在Google上找不到任何远程帮助.您可以提供的任何帮助将是非常感谢!! 谢谢!=)
首先,您需要配置 Apache Httpd 以请求客户端证书。为此,您至少需要在要使用SSLVerifyClient optional
此方法进行身份验证的位置/目录上使用。
其次,客户端发送的证书也需要被Apache Httpd信任。(原则上您可以使用SSLVerifyClient optional_no_ca
, 让任何客户端证书通过 Apache Httpd SSL/TLS 堆栈,然后才在 PHP 中验证证书,但这是相当多的工作,为此您需要更加小心,因为那不是必然是简单的代码;更重要的是,在这种情况下,这将毫无用处,因为您处于可以控制 CA 的场景中。)
据我所知,SSL_CLIENT_VERIFY
(我自己很少使用的变量)似乎只对SSLVerifyClient optional_no_ca
. 它可能适用于SSLVerifyClient optional
,但我对此表示怀疑。SSLVerifyClient require
将拒绝使用不受信任的客户端证书(由SSLCACertificateFile
/中的 CA 之一SSLCACertificatePath
)或如果没有证书的连接。据我所知,SSLVerifyClient optional
将让客户端在没有证书或受信任证书的情况下通过,但如果证书不受信任,也会拒绝连接。
在这里,拒绝连接的意思是突然关闭 SSL/TLS 连接并发出警报。没有机会产生 HTTP(S) 错误页面。所有你会在标准浏览器错误中得到的,类似于ssl_error_unknown_certificate_...
. (您应该从可用性的角度考虑这一点。)
从那时起,您需要的是设置您自己的 CA,可能基于 Web 并在浏览器内生成密钥并在同一网站内。您不希望SSLVerifyClient require
这样做,因为您需要让还没有证书的用户进入(optional
改为使用)。话虽如此,这些指令不需要适用于整个主机,但可以特定于某些位置/目录。
如果您不熟悉这一切,那么集成您自己的基于 Web 的 CA(或更一般地说,创建您自己的 CA)并不一定容易。存在现成的工具(例如OpenCA),或者您可以使用各种JavaScript/ActiveX构建自己的工具,并且您需要服务器端代码来处理 SPKAC 或 PKCS#10 请求(并颁发实际证书) . (为了使这样的 CA 有用,您希望申请新证书的用户在申请时提供一些 ID 证明,可能是密码。)
设置完成后,您应该配置SSLCACertificateFile
(或...Path
)指向内部 CA 的 CA 证书(无论它是否是基于 Web 的 CA,是否在同一站点上)。(当然,将您的 CA 的私钥保密,可能是在您的基于 Web 的 CA 应用程序中配置的,但 Apache Httpd 本身不需要知道它。)浏览器只会建议由这些 CA 或中间机构颁发的证书(除非您还配置了SSLCADNRequestFile
,它将用于发送已接受的 CA 列表)。
请注意,这两个步骤(设置 CA 和设置网站以使用客户端证书)实际上是独立的。两者都可以属于同一个站点的事实可能很方便,但不是必需的。您可以在不首先在站点上部署整个 CA 的情况下尝试 Apache Httpd 设置(我建议这样做,即使只是为了看看您要进入什么)。有许多工具可以创建您自己的小型 CA,这些工具可以使用少量证书进行管理:例如OpenSSL 的 CA.pl或TinyCA。你也可以使用这些测试证书(localhost
和testclient
,testclient_r
被撤销,如果你想使用CRL,最初可能没有必要):所有密码都是testtest
。
正如您已经预料到的(使用您的 MySQL 数据库),您需要管理您颁发的证书并将它们映射到用户。SSL_CLIENT_M_SERIAL
但是,SSL_CLIENT_I_DN
并不是要使用的正确变量。SSL_CLIENT_I_DN
是颁发者 DN(即 CA 的主题 DN)。您要寻找的是SSL_CLIENT_S_DN
:客户端证书主题 DN。SSL_CLIENT_M_SERIAL
是证书序列号:不要使用它,因为它是每个证书唯一的:一个用户可以拥有多个具有相同主题 DN 的证书(例如,如果一个证书过期或被撤销)。
尽管如此,我不确定客户证书是否是实现您目标的最佳方式(让您公司的员工无需密码即可登录)。
首先,用户无论如何都应该使用密码保护自己的证书。我猜您真正想要的是某种形式的单点登录 (SSO)。
其次,根据用户的计算机知识水平,证书实际上可能很难管理。
严格来说,“证书”一词根本不包括私钥,但有时暗示使用私钥这一事实可能会让某些人感到困惑。一方面,您有时会听到“将您的证书导入浏览器”和“使用您的证书登录”;另一方面,您还可以听到“将您的证书发送给我”。前者意味着私钥的使用和可用性(“证书”可能只是.p12
在这些表达中的意思)。后者绝对不应该涉及私钥。
浏览器用户界面在管理证书或注销时往往非常糟糕或令人困惑。同样,如果证书未被识别,则不会建立 SSL/TLS 连接,因此 Web 服务器没有机会显示任何类型的 HTML 错误页面。
也许您还可以考虑其他形式的 SSO(例如 CAS、基于 SAML 的东西或 Kerberos/SPNEGO。)
hor*_*bzz -2
如果尚未完成, 您可以查看apache 文档。
一般原则是您创建自签名证书并在尝试使用它之前检查它。
然后看起来客户端通过 http 连接到您的 Intranet 站点。从那里,有许多不同的方法可以使用您的 ssl 证书切换到 https。最简单的方法是使用 apache 重写模块。但就您而言,当您进行 php/mysql 检查时,您可能会将客户端从 http 重定向到 https,这不是简单的方法。
在这两种情况下(apache通过mod_rewrite自动重定向,或通过级联测试(php/javascript/html)重定向),您需要以正确的方式设置2个虚拟主机(一个用于http,一个用于https),但这假设一些假设。
例如(debian - apache 2.2),这是由 Apache 完成的自动重定向(例如上述第一种情况):
猫 /etc/apache2/sites-available/test
# VHOST test
<VirtualHost *:80>
DocumentRoot /home/www/test
ServerName www.test.dev
# ######################
# Redirect commons
# ######################
RewriteEngine on
# Case of vhosts
RewriteOptions Inherit
# ######################
# Redirect (empty index)
# ######################
# Condition 1 to redirect : request matching with the server
RewriteCond %{HTTP_HOST} ^www\.test\.dev [NC]
# Condition 2 to redirect : non empty HOST
RewriteCond %{HTTP_HOST} !^$
# Automatic Empty requests Redirect
RewriteRule ^(.*)/$ /index.php
# ######################
# Redirect to SSL
# ######################
RewriteCond %{HTTP_HOST} ^www\.test\.dev [NC]
RewriteCond %{HTTP_HOST} !^$
RewriteCond %{SERVER_PORT} ^80$
RewriteCond %{REQUEST_URI} /
# Redirection
RewriteRule ^/(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R]
</VirtualHost>
Run Code Online (Sandbox Code Playgroud)
SSL 的第二个虚拟主机:cat /etc/apache2/sites-available/test-ssl
# VHOST for ssl
Run Code Online (Sandbox Code Playgroud)
DocumentRoot "/home/www/test"
ServerName www.test.dev
# SSL
SSLEngine on
SSLCACertificateFile /etc/apache2/ssl/cur_cert/ca.pem
SSLCertificateFile /etc/apache2/ssl/cur_cert/serveur.pem
SSLCertificateKeyFile /etc/apache2/ssl/cur_cert/serveur.key
<Directory "/home/www/test">
Options FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
Allow from 127.0.0.1 192.168.0.0/16
</Directory>
<Directory "/home/www/test/cgi-bin">
Options FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
Allow from 127.0.0.1 192.168.0.0/16
Options +ExecCGI
AddHandler cgi-script .cgi
</Directory>
</VirtualHost>
Run Code Online (Sandbox Code Playgroud)
您的情况可能与此略有不同,例如,您在第一个虚拟主机中不会有重定向部分,而只有一个简单的虚拟主机,第二个虚拟主机用于 https (ssl)。一旦您完成 mysql 检查,重定向将由 php/javascript 完成。
下面是一个来自 php 类的抽象示例,说明如何级联从 http 到 https 的切换,先使用 php,然后使用 javascript,然后使用 html:
public function Redirect($url){
if (TRUE !== Validator::isValidURL($url))
die ("FATAL ERR: url not valid");
// PHP ABSOLUTE URL REDIRECT (HTTP1.1)
if (!headers_sent()) {
header("Status: 200");
header("Cache-Control: no-cache, must-revalidate"); // required for HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // past Date
header("Pragma: no-cache");
header('Location: '.$url); // note: 302 code return by default with "Location"
flush();
exit();
// if headers are already sent... do javascript redirect... if javascript is disabled, do html redirect.
} else {
// Js redirect
echo '<script type="text/javascript">';
//echo "<!--";
echo 'document.location="'. $url .'";';
//echo "//-->";
echo '</script>';
// HTML redirect if js disabled
echo '<noscript>';
echo '<meta http-equiv="refresh" content="0;url="'.$url.'" />';
echo '</noscript>';
exit();
}
return FALSE;
} /* end of method (redirect) */
Run Code Online (Sandbox Code Playgroud)
希望它可以帮助您更好地了解如何继续并根据您的具体情况调整此方法。