apache 使用 URL 重写通过 HTTPS 进行 HTTP 身份验证
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2220167/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Do HTTP authentication over HTTPS with URL rewriting
提问by Matthew
I am trying to protect the ~/public_html/devdirectory using http auth basic, but to make that secure I want to run it over ssl.
我正在尝试~/public_html/dev使用 http auth basic保护目录,但为了确保安全,我想通过 ssl 运行它。
The middle section of the below .htaccessfile switches to https if the request URI begins with /devand works.
.htaccess如果请求 URI 以 开头/dev并有效,则以下文件的中间部分将切换到 https 。
The last section of the file works as well but does not work properly with the https redirect.
该文件的最后一部分也能正常工作,但不能与 https 重定向一起正常工作。
I basically want to be able to type http://www.example.com/dev/some_sub_dir/and be redirected to https://www.example.com/dev/some_sub_dir/and prompted for the http auth username and password.
我基本上希望能够输入http://www.example.com/dev/some_sub_dir/并重定向到https://www.example.com/dev/some_sub_dir/并提示输入 http auth 用户名和密码。
What currently happens is if I go to http://www.example.com/dev/some_sub_dir/I get prompted for a username and password over port 80, and then immediately get prompted again over port 443. So my credentials are being sent twice, once in the clear, and once encrypted. Making the whole https url rewrite a little pointless.
当前发生的情况是,如果我转到http://www.example.com/dev/some_sub_dir/80 端口时会提示输入用户名和密码,然后立即通过端口 443 再次提示。因此我的凭据被发送两次,一次是明文,一次是加密。使整个 https url 重写有点毫无意义。
The reason for doing this is so that I won't be able to accidentally submit my user/pass over http; https will always be used to access the /devdirectory.
这样做的原因是为了我不会意外提交我的用户/通过http; https 将始终用于访问/dev目录。
The .htaccessis in the ~/public_html/devdirectory.
该.htaccess是在~/public_html/dev目录中。
# Rewrite Rules for example.com
RewriteEngine On
RewriteBase /
# force /dev over https
RewriteCond %{HTTPS} !on
RewriteCond %{REQUEST_URI} ^/dev
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
# do auth
AuthType Basic
AuthName "dev"
AuthUserFile /home/matt/public_html/dev/.htpasswd
Require valid-user
回答by siliconrockstar
There is a relatively popular hack to force HTTPS before doing Basic Authentication. I first saw it here:
在进行基本身份验证之前,有一种相对流行的 hack 方法可以强制使用 HTTPS。我第一次在这里看到它:
http://blog.jozjan.net/2008/02/htaccess-redirect-to-ssl-https-before.html
http://blog.jozjan.net/2008/02/htaccess-redirect-to-ssl-https-before.html
It involves using a custom error document to handle whatever happens after the HTTPS check fails.
它涉及使用自定义错误文档来处理 HTTPS 检查失败后发生的任何事情。
For example, I have a single page I need to force HTTPS on, so I did this in an .htaccess file:
例如,我有一个页面需要强制启用 HTTPS,因此我在 .htaccess 文件中执行了此操作:
<FilesMatch "secure-page.php">
SSLRequireSSL
ErrorDocument 403 https://www.example.com/secure-page.php
AuthType Basic
AuthName "Secure Page"
AuthUserFile /var/www/whatever/.htpasswdFile
Require valid-user
</FilesMatch>
Which translates to:
翻译成:
if the requested page is 'secure-page.php' - if not HTTPS, then redirect to a custom 'error page' - the 'error page' is actually just the HTTPS version of the page - on the second request, since the HTTPS check now passes, perform Basic Auth :)
如果请求的页面是“secure-page.php”——如果不是 HTTPS,则重定向到自定义的“错误页面”——“错误页面”实际上只是页面的 HTTPS 版本——在第二个请求中,因为 HTTPS现在检查通过,执行基本身份验证:)
You can extend this concept to a directory or other use cases - your custom 'error page' could be a php page that redirects to the correct HTTPS URL, or a CGI script like in the link above...
您可以将此概念扩展到目录或其他用例 - 您的自定义“错误页面”可以是重定向到正确 HTTPS URL 的 php 页面,也可以是上面链接中的 CGI 脚本...
回答by Jeff Davis
I ran into the same problem and finally found an ugly solution, but it works. Put the rewrite rule in a Directory directive in httpd.conf or one of your conf.d files (i.e., in the "Main" server configuration). Then, put the Auth* and Require lines in a Directory directive insidethe <VirtualHost _default_:443>container in ssl.conf (or wherever your SSL VirtualHost is defined).
我遇到了同样的问题,终于找到了一个丑陋的解决方案,但它有效。将重写规则放在 httpd.conf 或 conf.d 文件之一的 Directory 指令中(即,在“主”服务器配置中)。然后,将 Auth* 和 Require 行放在 ssl.conf 容器内的Directory 指令<VirtualHost _default_:443>中(或定义 SSL VirtualHost 的任何位置)。
For me, this means creating a file /etc/httpd/conf.d/test.confwith:
对我来说,这意味着创建一个文件/etc/httpd/conf.d/test.conf:
<Directory "/var/www/html/test">
#
# force HTTPS
#
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
</Directory>
...and then adding the following inside /etc/httpd/conf.d/ssl.confjust above the </VirtualHost>tag:
...然后/etc/httpd/conf.d/ssl.conf在</VirtualHost>标签上方添加以下内容:
<Directory "/var/www/html/test">
#
# require authentication
#
AuthType Basic
AuthName "Please Log In"
AuthUserFile /var/www/auth/passwords
Require valid-user
</Directory>
Doing this makes Apache apply the RewriteRule to all requests, and the auth requirements only to requests in the 443 VirtualHost.
这样做会使 Apache 将 RewriteRule 应用于所有请求,而 auth 要求仅适用于 443 VirtualHost 中的请求。
回答by zx81
Building on siliconrockstar's answer, I am adding a php script that would work in the case where you want to force SSL on allthe files, not just the one-file case shown by siliconrockstar. Here again it works in conjunction with the htaccess file.
以siliconrockstar 的回答为基础,我添加了一个php 脚本,该脚本适用于您想对所有文件强制使用SSL 的情况,而不仅仅是siliconrockstar 显示的单文件情况。这里再次与 htaccess 文件结合使用。
The htaccess to protect to whole directory:
保护整个目录的 htaccess:
SSLRequireSSL
ErrorDocument 403 /yourphp.php
AuthType Basic
AuthName "Secure Page"
AuthUserFile /some_path_above_the_html_root/.htpasswdFile
Require valid-user
The php called by the htaccess (the path given for the php in this sample htaccess is the root of your site), which forces https on the url you called:
htaccess 调用的 php(此示例 htaccess 中为 php 提供的路径是您站点的根目录),这会在您调用的 url 上强制使用 https:
<?php
$path = "https://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
if ( $_SERVER['SERVER_PORT'] == 80) {
header("Status: 302 Moved\n");
header("Location: ".$path."\n\n");
}
else {
header( "Content-type: text/html\n\n");
echo "How did you get here???";
}
?>
If your site doesn't have an SSL certificate, you'll have to install one. If this is your only use for it, you can install a self-signed certificate. On a cPanel VPS with your site on a dedicated IP, that takes moments to do: in WHM, visit
如果您的站点没有 SSL 证书,则必须安装一个。如果这是您的唯一用途,您可以安装自签名证书。在您的站点在专用 IP 上的 cPanel VPS 上,这需要一些时间:在 WHM 中,访问
One. Generate an SSL Certificate and Signing Request
一。生成 SSL 证书和签名请求
then
然后
Two. Install an SSL Certificate on a Domain
二。在域上安装 SSL 证书
回答by Will
Protecting content with basic authentication will never work securely over HTTP.
使用基本身份验证保护内容永远不会通过 HTTP 安全地工作。
Once the user has entered their username and password, it is sent unencrypted for every page view to that site - its not just sent the time the user gets prompted.
一旦用户输入了他们的用户名和密码,它就会在每次访问该站点的页面时以未加密的方式发送——它不仅仅是在用户收到提示时发送。
You have to treat requests over HTTP as un-authenticated, and do alllogged in stuff over HTTPS.
您必须将通过 HTTP 的请求视为未经身份验证,并通过 HTTPS执行所有登录的操作。
A lot of websites have used HTTPS for the login - using forms and cookies, rather than basic auth - and then go to HTTP afterwards. This means that their 'you are logged in' cookie gets sent unencrypted. Every valuable target has been hacked because of this, and gmail is now switching to full HTTPS and others will follow.
许多网站使用 HTTPS 进行登录 - 使用表单和 cookie,而不是基本身份验证 - 然后转到 HTTP。这意味着他们的“您已登录”cookie 将在未加密的情况下发送。因此,每一个有价值的目标都被黑客攻击了,gmail 现在正在切换到完整的 HTTPS,其他人也会效仿。
You don't have the same scaling issues that others have had that has kept them away from the computationally more expensive HTTPS. If your homepage supports HTTPS access, use it throughout.
您没有其他人遇到的相同的缩放问题,这些问题使他们远离计算成本更高的 HTTPS。如果您的主页支持 HTTPS 访问,请始终使用它。
回答by matsebt
If you place the rewrite rules in the main config, outside any or or similar, rewriting will be done before authentication.
如果您将重写规则放在主配置中,在任何或类似的外部,重写将在身份验证之前完成。
See Rewrite Tech
请参阅重写技术
回答by Will
Does it work to put your authentication section in a <Location>or <LocationMatch>tag using the protocol as the term?
使用协议作为术语将您的身份验证部分放在<Location>或<LocationMatch>标签中是否有效?
回答by Craig Smith
I know this is an old question but I had trouble with a simple ht.access redirect. Following many other problems and answers I finally put together this htaccess which works as intended.
我知道这是一个老问题,但我在使用简单的 ht.access 重定向时遇到了麻烦。在许多其他问题和答案之后,我终于将这个 htaccess 组合在一起,它按预期工作。
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
AuthName "Private Server"
AuthUserFile /var/www/.htpassword
AuthType Basic
require valid-user
Order allow,deny
Allow from env=!HTTPS
Satisfy Any
To note the
要注意
Order allow,deny
Which is what was missing from many other answers I have seen as it would allow people in directly when using https. The other section that was missing from my tests was the following:
这是我看到的许多其他答案中所缺少的,因为它允许人们在使用 https 时直接进入。我的测试中缺少的另一部分如下:
Satisfy Any
This following snippet is what allows non SSL clients in with for the redirect. The HTTPS env var is set from the mod_ssl for ssl clients.
以下代码段允许非 SSL 客户端进行重定向。HTTPS 环境变量是从 mod_ssl 为 ssl 客户端设置的。
Allow from env=!HTTPS
回答by hunteke
I have two answers to the question, one with a 2010 mindset, and one with a post-2012 mindset.
我对这个问题有两个答案,一个是 2010 年的心态,一个是 2012 年后的心态。
To answer this question as if it was 2010 when it was asked: use two different VirtualHost configurations.
要回答这个问题,就像被问到 2010 年一样:使用两种不同的 VirtualHost 配置。
This solution is a little outside the scope of the question as the implication is "I only have access to modify .htaccess!" but a viable solution in many cases is to request the administrator du jour to simply setup two different VirtualHost configurations.
这个解决方案有点超出了问题的范围,因为它的含义是“我只能访问修改.htaccess!” 但在许多情况下,一个可行的解决方案是要求日常管理员简单地设置两个不同的 VirtualHost 配置。
The non-SSL VirtualHost is not configured to access anything on the filesystem, and merely returns 301 redirects to
https://...locations for all requests.The SSL listening VirtualHost is then free to implement Basic Authentication without worry that the standard HTTP listener will give away the goods.
非 SSL VirtualHost 未配置为访问文件系统上的任何内容,仅返回 301 重定向到
https://...所有请求的位置。然后,SSL 侦听 VirtualHost 可以自由地实施基本身份验证,而不必担心标准 HTTP 侦听器会泄露商品。
However, with my post-2018 hat on, and noting that this question was asked before Apache 2.4 (early 2012?), it's time for an update. Apache 2.4 introduced <If condition>checks, which makes this much easier and more direct:
但是,随着我在 2018 年之后的帽子,并注意到这个问题是在 Apache 2.4(2012 年初?)之前提出的,是时候进行更新了。Apache 2.4 引入了<If condition>检查,这使得这更容易和更直接:
First, do not IfModule the RewriteEngine. As Apache is listening on both port 80 and 443 (in the standard setup), AND we want to enforce SSL, we want the server to break if the Rewrite module is otherwise disengaged.
RewriteEngine OnSecond, simply enough, perform an immediate and permanent (301) redirect if the request is not secure. Note the R(edirect) and L(ast) which work together to ensure that non-encrypted requests are redirected and can't be utilized to gain non-authenticated access. (For the OCD, non-copy-paste minded, note the lackof space between
!=andon. That is intentional.)RewriteCond %{HTTPS} !=on RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R=301,QSA,L,NC]Finally, use that same variable with an
<If-condition>check to ensure that we only require the password for TLS request.<If "%{HTTPS} == 'on'"> AuthName "Password please!" AuthType Basic AuthUserFile /path/to/htpasswdfile AuthGroupFile /dev/null require valid-user </If>
首先,不要使用 IfModule 的 RewriteEngine。由于 Apache 正在侦听端口 80 和 443(在标准设置中),并且我们想要强制执行 SSL,如果 Rewrite 模块以其他方式脱离,我们希望服务器中断。
RewriteEngine On其次,很简单,如果请求不安全,则执行立即和永久 (301) 重定向。请注意 R(edirect) 和 L(ast),它们一起工作以确保未加密的请求被重定向,并且不能用于获得未经身份验证的访问。(对于强迫症,不喜欢复制粘贴,请注意和之间缺少空格。这是故意的。)
!=onRewriteCond %{HTTPS} !=on RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R=301,QSA,L,NC]最后,使用相同的变量进行
<If-condition>检查以确保我们只需要 TLS 请求的密码。<If "%{HTTPS} == 'on'"> AuthName "Password please!" AuthType Basic AuthUserFile /path/to/htpasswdfile AuthGroupFile /dev/null require valid-user </If>
And altogether:
总而言之:
# .htaccess
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R=301,QSA,L,NC]
<If "%{HTTPS} == 'on'">
AuthName "Password please!"
AuthType Basic
AuthUserFile /path/to/htpasswdfile
AuthGroupFile /dev/null
require valid-user
</If>
回答by Ben
I get around it this way. Just allow Non-SSL since it will be redirected then require auth once on SSL...
我是这样绕过的。只允许非 SSL,因为它将被重定向,然后需要在 SSL 上进行一次身份验证...
SetEnvIf %{SERVER_PORT} ^80$ IS_NON_SSL
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
AuthUserFile /.htpasswd
AuthName "Enter your Username and Password:"
AuthType Basic
require valid-user
Allow from env=IS_NON_SSL

