Apache 忽略的 .htaccess 标头

.htaccess headers being ignored by Apache

提问人:Martin 提问时间:11/12/2018 最后编辑:CommunityMartin 更新时间:3/28/2021 访问量:11978

问:

我有一个网站,它使用与许多其他网站相同的核心细节;但是,此网站没有正确加载指令 - 给出一个基本的HTTP标头集:.htaccess.htaccess

    HTTP/1.1 200 OK
    Date: Mon, 12 Nov 2018 09:34:28 GMT
    Server: Apache
    Keep-Alive: timeout=5, max=100
    Connection: Keep-Alive
    Transfer-Encoding: chunked
    Content-Type: text/html; charset=UTF-8

网站本身加载正常,但 .htaccess 中的附加标头未被确认/加载。

所以被阅读,对吧?.htaccess

是 -- htaccess 文件包含 HTTPS 强制重定向和域名重定向(从 .co.uk 到 .com 地址(两者都到同一个网站帐户))

这些工作。

PHP 提供的标头也加载得很好

测试页面上的 PHP 标头加载良好:

<?php
header("Cache-Control: no-cache, must-revalidate");
header('Content-Type: text/html; charset=utf-8');
header("X-Clacks-Overhead: GNU Terry Pratchett");
header("Content-Language: en");
header("X-XSS-Protection: 1; mode=block");
header("X-Frame-Options: SAMEORIGIN");
header("X-Content-Type-Options: nosniff");
?>

但是,在 中设置的相同标头未被确认。.htaccess

所以这是一个语法错误!.htaccess

不是我能看到的;通常,站点会加载 HTTP-500 错误消息,但此处站点会在浏览器中加载而不会出现问题。

存在故意的语法错误时,error-500 HTTP 响应将按预期返回。

好的 bozo,检查您的错误日志!

绝对;我完全同意。Apache 错误日志为空!

你试图做些什么来解决这个问题?

  • 已确认允许读取httpd.conf.htaccess
  • 已确认服务器上已加载mod_headers.c
  • 注释掉并重写了各种规则,但没有任何效果
  • 阅读大量(可能是 6-8 篇)关于 Stack Overflow 和 Server Fault 的帖子 - Stackoverflow 帖子似乎没有关联,或者它们的问题有明显的差异。
  • 确认我有正确的权限 (0644).htaccess
  • 告诉我的员工(他是一名平面设计师)。
  • 哭着睡着了。

马上 - 把你的文件拿出来!让我看看魔法!

这里:

Options +FollowSymLinks
Options -Indexes
RewriteEngine On
ErrorDocument 404 /index.php?msg=404
ErrorDocument 403 /index.php?msg=403

#Set asset items to cache for 1 week.
<FilesMatch "\.(gif|jpe?g|png|ico|css|js|swf|mp3)$">
     Header set Cache-Control "max-age=1972800, public, must-revalidate"
</FilesMatch>

RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

## This does not appear to work (for either)
#Header always set Strict-Transport-Security "max-age=31536000;" env=HTTPS
Header always set Strict-Transport-Security "max-age=31536000; includeSubdomains;" "expr=%{HTTPS} == 'on'"
Header set Expect-CT enforce,max-age=2592000

RewriteCond %{HTTP_HOST} ^(www\.)?thewebsite\.co\.uk$ [NC]
RewriteRule ^/?(.*)$ https://www.thewebsite.com%{REQUEST_URI} [R=301,L]

###
##### Seems to workdown to roughly this point.
###

#force requests to begin with a slash.
RewriteCond  %{REQUEST_URI}  !^$
RewriteCond  %{REQUEST_URI}  !^/
RewriteRule  .*              -    [R=403,L]

RewriteCond %{HTTP_HOST} !^$
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule .* - [L]

### This file does not exist on the directory at present. 
<Files .account-user.ini>
    order allow,deny
    deny from all
</Files>

###
#### None of these appear on assessment tools such as Security Headers 
#### Or redbot.
###
Header set Cache-Control no-cache,must-revalidate
Header set X-Clacks-Overhead "GNU Terry Pratchett"
Header set X-XSS-Protection 1;mode=block
Header set X-Content-Type-Options nosniff
Header always set X-Frame-Options SAMEORIGIN
Header set Expect-CT enforce,max-age=2592000
Header set Content-Language en
Header set Referrer-Policy origin-when-cross-origin
    
<LimitExcept GET POST HEAD>
    deny  from all
</LimitExcept>

最后,如果你给我一个以上所有内容的最终总结,那将非常有帮助!

  • 中的标头设置命令似乎不起作用。.htaccess
  • 该文件的所有部分都可以在其他地方的其他实时站点上使用,而不会出现问题。
  • 可以在 PHP 中毫无问题地设置标头
  • 这些标头不会产生任何错误。.htaccess
  • 标头似乎以静默方式失败。
  • 不会记录任何 Apache 错误日志。
  • Apache 正在读取 ,因为其他命令(如 s)正在执行.htaccessmod_Rewrite

更新:

从其他方(托管服务提供商)的研究来看,似乎以某种方式工作并加载了非PHP页面的所有正确标题。.htaccess

即使是普通的PHP页面;标头为空。

澄清

  • 无论 .html 页面加载标题都正常。
  • PHP 页面显示由Header("...");
  • PHP 页面拒绝加载 设置的任何标头。这就是问题所在。.htaccess

所以看起来我无法为 PHP 页面设置标题。我该如何解决这个问题?.htaccess

php apache .htaccess

评论

0赞 digijay 11/13/2018
您是否尝试过 AllowOverride All?httpd.apache.org/docs/2.4/en/mod/core.html#allowoverride
0赞 Martin 11/13/2018
@D.Joe,如果允许覆盖处于关闭状态,则htaccess中的其他命令也将失败。如前所述,HTTPS 和命令确实按预期工作。www.
0赞 Martin 11/13/2018
@D.Joe,我已经更新了问题,以更好地突出这一点。
0赞 digijay 11/14/2018
那么它必须mod_headers。那是Debian/Ubuntu服务器吗?你能在这里检查配置和/或发布它们吗?/etc/apache2/mods_enabled/headers.conf.load
1赞 Álvaro González 11/25/2018
您是否偶然将 PHP 作为 CGI 运行?如果是这样,我自己也遇到了同样的问题:Apache不会为PHP脚本设置标头

答:

13赞 digijay 11/24/2018 #1

在作为 FastCGI 模块工作时,PHP 似乎忽略了 .htaccess 中定义的标头。

有很多建议可以解决这个问题。就您而言,我建议您使用一个定义所有标头的文件

<?php
// file headers.php
header('Cache-Control: no-cache,must-revalidate');
header('X-Clacks-Overhead: "GNU Terry Pratchett"');
header('X-XSS-Protection: 1;mode=block');
header('X-Content-Type-Options: nosniff');
header('X-Frame-Options: SAMEORIGIN');
header('Expect-CT: enforce,max-age=2592000');
header('Content-Language: en');
header('Referrer-Policy: origin-when-cross-origin');
?>

并将其保存到 DocumentRoot 目录。然后将此条目添加到您的 .htaccess 文件中,以将其包含在每个请求中:

php_value auto_prepend_file /var/www/html/headers.php     

测试它:

<?php
// file test.php
die("hello world");
?>

并且正在发送标头:

$ curl -I ubuntu-server.lan/test.php
HTTP/1.1 200 OK
Date: Sun, 25 Nov 2018 09:37:52 GMT
Server: Apache/2.4.18 (Ubuntu)
Cache-Control: no-cache,must-revalidate
X-Clacks-Overhead: "GNU Terry Pratchett"
X-XSS-Protection: 1;mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Expect-CT: enforce,max-age=2592000
Content-Language: en
Referrer-Policy: origin-when-cross-origin
Content-Type: text/html; charset=UTF-8

永远记住,当您在 .htaccess 中更改标头时,也要在标头 .php 中更改它们。

希望这有帮助!


➥ 上一个答案

我认为这个问题是由于 httpd/apache2 未正确加载造成的(尽管您在上述评论之一中另有说明)。您可以通过在终端中执行以下命令来检查这一点:headers_module

apachectl -M | grep headers_module

如果你没有得到任何输出(或类似的),那么你必须激活 httpd/apache2 headers 模块。在 CentOS 系统上,您必须在配置中加载相应的源文件(默认)。headers_module (shared)/etc/httpd/conf/httpd.conf

您必须添加此行

LoadModule headers_module /usr/lib/apache2/modules/mod_headers.so

然后重新启动 HTTP 服务器sudo systemctl restart httpd.service

在 EasyApache 4 中,httpd/apache2 模块所在的文件夹可能会有所不同,并且是 ./usr/lib64/apache2/modules/

我希望这会有所帮助!

评论

0赞 Martin 11/28/2018
谢谢你在这里的帮助,D.joe,但我只能给一个赏金,你已经得出了一些与他们得到的非常相似的结论——这是FastCGI,虽然我很欣赏你的回答,但它更像是一种解决方法,而不是使用Fast-CGI的解决方案。谢谢covener
0赞 Chad Cloman 2/27/2019
@digijay 这很好用,但有一个警告。使用 FastCGI 处理程序是导致问题的原因。但是此注释中给出的指令是针对mod_php处理程序的。因此,将该行添加到将不起作用。相反,您必须使用以下内容创建一个 PHP 配置文件(例如 ):php_value.htaccess.user.iniauto_prepend_file = /var/www/html/headers.php
0赞 Beerswiller 10/23/2019
我花了 4 个小时试图弄清楚为什么 CORS 在 API 中排除了 php 生成的服务器响应,答案一直都在这里!该死的 FastCGI!如果您在浏览器中收到消息,<code>Access to XMLHttpRequest at <API source> from origin <www caller> 已被 CORS 策略阻止:请求的 resource.</code 上不存在“Access-Control-Allow-Origin”标头>这是因为您只查看 .htaccess 来设置标头。如果在 FastCGI 中强制使用 PHP,则需要使用上述解决方案在 PHP 文件中设置它
0赞 Mr J Wolf 2/2/2023
@ChadCloman 如果添加到 ,我还需要吗?auto_prepend_file = /var/www/html/headers.php.user.iniphp_value auto_prepend_file /var/www/html/headers.php.htaccess
1赞 Chad Cloman 2/3/2023
@MrJWolf It's my understanding that both have the same effect, and that you only need one.
10赞 covener 11/25/2018 #2

It is not so much FastCGI as it is mod_proxy_fcgi, the method of asking Apache to "execute" FastCGI by passing it to some other listener.

When you use any mod_proxy* module, .htaccess isn't processed at all, because you're acting as a proxy and short-circuiting any disk-related configuration sections.

php-fpm will be looking at the request URL and reading data from disk, but Apache isn't. It is just confusing to people because they can be running on the same host and the files are often in a directory httpd could serve directly.

评论

0赞 Martin 11/26/2018
I found the handler was the cause -- swapping from a CGI to a suphp handler immediately resolved the issues. I a not sure if it was anything to do with proxys but the hander, yes. Cheers
0赞 Martin 11/26/2018 #3

After much exploration it was found the issue was the PHP Handler -- the (cgi) handler was not keeping the headers. fastCGI

Changing to the handler immediately resolved the issues.suphp

评论

0赞 Martin 11/28/2018
@swa66 this is the solution. Regardless of me finding it myself or elsewhere. BOTH other answers insinuate a similar solution (aka fast-CGI to blame) and that actually makes it more tricky....
0赞 Vahid Montazer 3/20/2019 #4

I had same problem. Please enable module in Linux Ubuntu.cache

sudo a2enmod cache

Then run:

sudo service apache2 start