通过URL重写进行HTTP身份验证

时间:2010-02-08 07:43:37

标签: apache .htaccess mod-rewrite url-rewriting http-authentication

我正在尝试使用http auth basic来保护~/public_html/dev目录,但为了使其安全,我想在ssl上运行它。

如果请求URI以.htaccess开头并且有效,则下面/dev文件的中间部分会切换到https。

该文件的最后一部分也可以正常工作,但无法正常使用https重定向。

我基本上希望能够输入http://www.example.com/dev/some_sub_dir/并重定向到https://www.example.com/dev/some_sub_dir/并提示输入http auth用户名和密码。

目前发生的情况是,如果我转到http://www.example.com/dev/some_sub_dir/我会收到提示输入端口80上的用户名和密码,然后立即再次通过端口443提示。所以我的凭据被发送两次,一次清除,一旦加密。使整个https url重写有点无意义。

这样做的原因是我无法意外地通过http提交我的用户/传递; https将始终用于访问/dev目录。

.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

9 个答案:

答案 0 :(得分:10)

在进行基本身份验证之前,有一种相对流行的黑客强制HTTPS。我第一次看到它:

http://blog.jozjan.net/2008/02/htaccess-redirect-to-ssl-https-before.html

它涉及使用自定义错误文档来处理HTTPS检查失败后发生的任何事情。

例如,我有一个页面需要强制启用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>

转换为:

如果请求的页面是'secure-page.php' - 如果不是HTTPS,则重定向到自定义'错误页' - '错误页'实际上只是页面的HTTPS版本 - 在第二个请求中,由于HTTPS检查现在通过,执行Basic Auth:)

您可以将此概念扩展到目录或其他用例 - 您的自定义“错误页面”可能是重定向到正确的HTTPS URL的php页面,或者像上面链接中的CGI脚本......

答案 1 :(得分:4)

我遇到了同样的问题,终于找到了一个丑陋的解决方案,但它确实有效。将重写规则放在httpd.conf中的Directory指令或其中一个conf.d文件中(即“主”服务器配置中)。然后,将Auth *和Require行放在ssl.conf中的<VirtualHost _default_:443>容器中的目录指令 中(或者定义SSL VirtualHost的任何位置)。

对我来说,这意味着使用以下内容创建文件/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>

...然后在/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>

这样做会使Apache将RewriteRule应用于所有请求,而auth只要求443 VirtualHost中的请求。

答案 2 :(得分:4)

基于siliconrockstar的答案,我正在添加一个php脚本,该脚本适用于您希望在所有文件上强制使用SSL的情况,而不仅仅是sirockstar显示的单文件情况。这里再次与htaccess文件一起使用。

保护整个目录的htaccess:

    SSLRequireSSL
    ErrorDocument 403 /yourphp.php
    AuthType Basic
    AuthName "Secure Page"
    AuthUserFile /some_path_above_the_html_root/.htpasswdFile
    Require valid-user

由htaccess调用的php(此示例htaccess中为php提供的路径是您网站的根目录),强制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???";
}
?>

如果您的网站没有SSL证书,则必须安装一个。如果这是您的唯一用途,则可以安装自签名证书。在cPanel VPS上,您的站点位于专用IP上,需要时间:WHM,请访问

一。生成SSL证书和签名请求

然后

两个。在域上安装SSL证书

答案 3 :(得分:2)

使用基本身份验证保护内容永远不会通过HTTP安全地工作。

一旦用户输入了他们的用户名和密码,它就会以未加密的方式发送给该网站的每个页面视图 - 它不仅仅是发送用户被提示的时间。

您必须将HTTP上的请求视为未经过身份验证,并通过HTTPS执行所有登录的内容。

许多网站都使用HTTPS进行登录 - 使用表单和cookie,而不是基本身份验证 - 之后再转到HTTP。这意味着他们的“您已登录”cookie将以未加密的方式发送。因此,每个有价值的目标都被黑客入侵,而gmail现在正在切换到完整的HTTPS,其他人将会跟进。

您没有与其他人一样的缩放问题,这使他们远离计算上更昂贵的HTTPS。如果您的主页支持HTTPS访问,请始终使用它。

答案 4 :(得分:1)

如果您将重写规则放在主配置中,在任何或类似之外,重写将在验证之前完成。

请参阅Rewrite Tech

答案 5 :(得分:0)

使用协议作为术语,将您的身份验证部分放在<Location><LocationMatch>标记中是否有效?

答案 6 :(得分:0)

我这样绕过它。只允许非SSL,因为它将被重定向,然后在SSL上需要auth一次...

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

答案 7 :(得分:0)

我知道这是一个老问题,但我遇到了一个简单的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

注意

Order allow,deny

我看到的许多其他答案中缺少的是因为它可以让人们直接使用https。我的测试中缺少的另一部分如下:

Satisfy Any

以下代码段允许非SSL客户端用于重定向。 HTTPS env var是从ssl客户端的mod_ssl设置的。

Allow from env=!HTTPS

答案 8 :(得分:0)

我对这个问题有两个答案,一个是2010年的心态,另一个是2012年后的心态。

要回答这个问题,就好像它是在2010年被问到的那样:使用两种不同的VirtualHost配置。

这个解决方案有点超出了问题的范围,因为含义是&#34;我只能修改.htaccess!&#34;但在许多情况下,一个可行的解决方案是请管理员简单地设置两个不同的VirtualHost配置。

  • 非SSL VirtualHost未配置为访问文件系统上的任何内容,仅返回301重定向到所有请求的https://...位置。

  • SSL侦听VirtualHost随后可以自由实现基本身份验证,而无需担心标准HTTP侦听器会泄露货物。

然而,随着我的2018年后的问题,并注意到在Apache 2.4(2012年初?)之前提出这个问题,是时候进行更新了。 Apache 2.4引入了<If condition>检查,这使得这更容易,更直接:

  • 首先,不要IfModule RewriteEngine。由于Apache正在侦听端口80和443(在标准设置中),并且我们希望强制执行SSL,因此如果Rewrite模块以其他方式脱离,我们希望服务器中断。

    RewriteEngine On 
    
  • 其次,如果请求不安全,请执行即时和永久(301)重定向。注意R(edirect)和L(ast)共同工作以确保重定向非加密请求并且不能用于获得非认证访问。 (对于OCD,非复制粘贴,请注意!=on之间缺少的空间。这是故意的。)

    RewriteCond %{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>
    

总而言之:

# .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>