.htaccess

一、 .htaccess 简介

1. 什么是 .htaccess

.htaccess 是一个纯文本文件,里面存放着 Apache 服务器配置相关的一些指令,它类似于 Apache 的站点配置文件,如 httpd.conf Apache2 已经支持多站点,因此你的站点配置文件可能在 /etc/apache2/conf.d/ 目录下)。

.htaccess httpd.conf 配置文件不同的是,它只作用于当前目录。另外 httpd.conf 是在 Apache 服务启动的时候就加载的,而 .htaccess 只有在用户访问目录时加载,开销大、速度慢。

既然如此,为什么我们还要用 .htaccess 呢?因为它配置起来简单,它还支持重定向、 URL 重写以及访问验证,另外它管理起来很方便,可以很好适应网站迁移。总之,各有优缺点,主要就看你是要从全局考虑还是只配置单个目录。

2.AllowOverride All

通常情况下, Apache 是默认启用 .htaccess 的,但是为了以防万一,请检查一下自己站点的配置文件,如 httpd.conf ,是否有这行:

1.AllowOverride All

这行允许重写配置文件。也就是如果能够从 .htaccess 加载配置文件,那么就以 .htaccess 为配置文件对其所在目录进行配置。

3.500 错误

如果你租用了云服务提供商的主机或者空间,那么他们可能不会给你读写 httpd.conf 文件的权限,你也不可能检查 AllowOverride 命令参数是否为 All ,这时,你可以新建一个目录,在里面写一个 .htaccess 文件,文件中随意写入一些服务器看不懂的东西,然后访问该目录里的一个页面,耐心等待 500 错误的出现。

如果没有出现,那么 .htaccess 没有被启用,你需要向你的服务供应商寻求帮助;如果出现了,那么恭喜你,你可以对当前目录重写 Apache 配置。

/!\ 注意 .htaccess 语法错误可能会影响整个站点,如果你不确定这样做是否安全,请联系你的云服务供应商。

二、 .htaccess 访问控制 (Allow/Deny)

1. 访问控制基础: Order 命令

为了限制用户访问一些关键目录, .htaccess 可以提供目录访问限制。你只需要在要限制的目录中,加入如下 .htaccess 文件:

1.# no one gets in here!

2.deny from all

这会限制所有用户通过浏览器访问该目录,这太一刀切了,因此我们还可以增加一些特定的条件,如允许指定 IP 地址的访问:

1.Order Allow , Deny

2.Deny from All

3.Allow from 192.168 . 0.0 / 24

Order 命令是一个难点,也是配置 apache 的基础,它决定了 Apache 处理访问规则的顺序。

通过 Allow,Deny 参数, Apache 首先找到并应用 Allow 命令,然后应用 Deny 命令,以阻止所有访问。

通过 Deny,Allow 参数, Apache 首先找到并应用 Deny 命令,然后应用 Allow 命令,以允许所有访问。

了解 Order 的用法后,再仔细考虑下上面的例子,你或许能够发现 Deny 命令是多余的,以下用法和之前的描述语义相同:

1.Order Allow , Deny

2.Allow from 192.168 . 0 / 24

2. 利用 .htaccess 过滤域名或网络主机 (Allow/Deny)

下例可以限制所有含有 "domain.com" 的网络主机访问网站:

1.Order Allow , Deny

2.Allow from all

3.Deny from .*domain\.com.*

3. 利用 .htaccess 禁止访问指定文件 (Files)

Files 命令可以用于过滤指定文件:

1.# secure htaccess file

2.< Files .htaccess>

3. order allow,deny

4. deny from all

5.</ Files >

4. 利用 .htaccess 禁止访问指定文件类型 (FilesMatch)

下面的代码将限制访问所有 .log .exe 文件:

1.< FilesMatch ".(log|exe)%HTML_CONTENT%quot; >

2. Order allow,deny

3. Deny from all

4.</ FilesMatch >

我们还可以通过 Files 命令描述文件类型,但是需要在命令后面加一个波浪线 (~) ,该符号启用 Files 命令的正则表达解析功能:

1.< Files ~ "^.*\.([Ll][Oo][Gg])|([eE][xX][eE])" >

2. Order allow,deny

3. Deny from all

4. Satisfy All

5.</ Files >

有以下几点需要读者注意:

Files 之后的波浪线用于开启 " 正则表达式 " 分析。请注意,这是个过时的用法, \\l "files" \\t "_blank" Apache 更推荐使用 <FilesMatch> 指令。

正则表达式必须在双引号之间。

双引号中的 " 管道符 "(|) 用于将两种文件类型( .log .exe )分开,相当于逻辑 " "

Order 命令必须嵌在 Files (Section) 中,否则将会应用到所有文件

Satisfy All 表示必须同时满足主机级别 (Allow/Denay) 和用户级别 (Require) 的限制, All 是默认值,该行可以省略。

三、利用 .htaccess 进行密码保护与验证

1. 配置 .htaccess

1.AuthType Basic

2.AuthName "restricted area"

3.AuthUserFile /usr/ local /var/www/html/.htpasses

4.require valid-user

这个配置文件可以保护 .htaccess 所在的整个目录,简单说明下参数:

AuthType :验证类型为基本类型,密码以明文方式传输到服务器上

AuthName :验证提示,会出现在验证对话框中

AuthUserFile :验证配置文件,用于匹配用户名与密码,该密码是加密保存的

require valid-user :只有在 AuthUserFile 中出现的用户才可以通过验证

如果验证失败,则会出现 401 错误。

2. 生成 .htpasses 文件

如何生成 .htpasses 文件呢?我们通过 htpasswd 命令生成密码文件:

1.htpasswd -c /usr/ local /var/www/html/.htpasses lesca

它会提示你输入密码,并确认。之后将密码文件 .htpasses 保存在 /usr/local/var/www/html/ 目录下。

3. 对文件进行密码保护

保护与 .htaccess 在同一目录下的文件 secure.php

1.# password-protect single file

2.< Files secure.php>

3.AuthType Basic

4.AuthName "Prompt"

5.AuthUserFile /home/path/.htpasswd

6.Require valid-user

7.</ Files >

保护 .htaccess 所在目录下的多个文件:

1.# password-protect multiple files

2.< FilesMatch "^(execute|index|secure|insanity|biscuit)*%HTML_CONTENT%quot; >

3.AuthType basic

4.AuthName "Development"

5.AuthUserFile /home/path/.htpasswd

6.Require valid-user

7.</ FilesMatch >

4. 对指定 IP 进行密码保护

仅允许 IP 地址为 99.88.77.66 的主机直接访问该目录,其他 IP 需要验证。

1.AuthType Basic

2.AuthName "Personal"

3.AuthUserFile /home/path/.htpasswd

4.Require valid-user

5.Allow from 99.88 . 77.66

6.Satisfy Any

5. 安全性

出于安全考虑,将 .htpasses 文件存放在 WEB 目录树之外也许是个好方法,但是由于 .htpasses 是隐藏文件,而且 Apache 不会输出隐藏文件,因此可以满足基本的安全要求。这是通过在主配置文件中加入如下限制实现的:

1.< Files ~ "^\.ht" >

2. Order allow,deny

3. Deny from all

4. Satisfy All

5.</ Files >

一般而言,这是默认设置,用户无需手动添加。我们唯一需要担心的是密码在网络传输过程中是 明文 形式,这很容易被黑客破译。 Coz 提供了一个开源项目 Pajamas 可以在本地利用 JS 对密码进行 MD5 加密,有兴趣的读者可以前去研究一下。

四、目录浏览与主页

1. 启用目录浏览

1.# enable directory browsing

2.Options All + Indexes

2. 禁用目录浏览

1.# disable directory browsing

2.Options All - Indexes

我们还可以通过 IndexIgnore 指令来禁用目录浏览。

1.# prevent folder listing

2.IndexIgnore *

通过 IndexIgnore 指令,我们可以禁止对指定类型的文件浏览:

1.# prevent display of select file types

2.IndexIgnore *.wmv *.mp4 *.avi *.etc

3. 自定义目录浏览

如果你希望 Apache 在展示你的 WEB 目录时看起来与众不同,那么你需要启用 FancyIndexing 选项:

1.< IfModule mod_autoindex.c>

2. IndexOptions FancyIndexing

3.</ifModule>

通过这个选项,你可以实现自定义图标、添加文件类型描述、按日期排序等。

4. 配置目录主页文件

即使启用了目录浏览, Apache 未必会展示该目录的内容,因为该目录可能存在像 index.htm 这样的默认主页文件。 Apache 会有限展示主页文件,我们可以通过 .htaccess 设置:

1.DirectoryIndex index.html index.php index.htm

5. 配置错误页面

如果 Apache 遇到错误,就会输出错误页面。配置自定义的错误页面,也许可以挽留即将离开的用户。

1.# custom error documents

2.ErrorDocument 401 /err/ 401.php

3.ErrorDocument 403 /err/ 403.php

4.ErrorDocument 404 /err/ 404.php

5.ErrorDocument 500 /err/ 500.php

五、.htaccess正则表达式

1.# 位于行首时表示注释。

2.[F] Forbidden(禁止) : 命令服务器返回 403 Forbidden错误给用户浏览器

3.[L] Last rule(最后一条规则) : 告诉服务器在本条规则执行完后停止重写URL

4.[N] Next(下一条规则) : 告诉服务器继续重写,指导所有重写指令都执行过

5.[G] Gone(丢失) : 命令服务器返回410 GONE(no longer exists)错误消息

6.[P] Proxy(代理) : 告诉服务器通过mod_proxy模块处理用户请求

7.[C] Chain(捆绑) : 告诉服务器将当前的规则和前面的规则进行捆绑

8.[R] Redirect(重定向) : 命令服务器发出重定向消息,以便用户浏览器发出rewritten/modified(重写/修改)URL的请求

9.[NC] No Case(不区分大小写) : 对客户端请求的URL不区分大小写

10.[PT] Pass Through(放行) : 让mod_rewrite模块将重写的URL传回给Apache做进一步处理

11.[OR] Or(逻辑或) : 用逻辑"或"将两个表达式连接在一起,如果结果为"真",则会应用后继的相关规则

12.[NE] No Escape(禁用转义) : 命令服务器在输出时禁用转义字符

13.[NS] No Subrequest(禁用子请求) : 如果存在内部子请求,则跳过当前命令

14.[QSA] Append Query String(追加查询字符串) : 命令服务器在URL末尾追加查询字符串

15.[S=x] Skip(跳过) : 如果满足某指定的条件,则跳过后面第x调规则

16.[E=variable:value] Environmental Variable(环境变量) : 命令服务器将值value赋给变量variable

17.[T=MIME-type] Mime Type(MIME类型) : 声明目标资源所属的MIME类型

18.[] 匹配一个字符集合,例如[xyz]可以匹配x, y或者z

19.[]+ 例如[xyz]+会以任何顺序、次数匹配x,y,z的出现

20.[^] 字符^表示字符集的补集。[^xyz]将匹配没有x,y或者z的字符串

21.[a-z] 连字符(-)表示匹配从字母a到字母z的所有字符串

22.a{n} 指定字母a出现的次数为n次,满足该条件时匹配。例如x{3}仅与xxx匹配

23.a{n,} 指定字母a出现的次数至少为n次,例如x{3,}可以与xxx或者xxxx等匹配

24.a{n,m} 指定a出现的次数至少为n到m次。

25.() 用于将正则表达式分组,满足第一组正则表达式的字符串会被存储在变量$1中,以此类推。如果括号中的不是正则表达式,例如(perishable)?press 将能够匹配有或者没有perishable前缀的press

26.^ 位于行首。注意:和中括号中的[^]意义不同。

27.$ 位于行末

28.? 例如 monzas? 会匹配 monza 或者 monzas,而 mon(za)? 会匹配 mon 或者 monza。又如 x? 会匹配"空字符" 或者 一个x

29.! 逻辑非。例如"!string" 将会匹配除了"string"以外的所有字符串

30.. 表示任意字符串

31.- 命令Apache"不要"重写URL,例如"xxx.domain.com.*  [F]"

32.+ 匹配至少一个任意字符,例如G+匹配以G开头、并且后面至少有一个字符的字符串

33.* 匹配零个或多个字符,例如".*"匹配任意字符串

34.| 逻辑"或",与[OR]不同的是,它只匹配字符串,例如(x|y)匹配x或者y

35.\ 转义字符。可以转义左括号( 尖字符^ 美元符号$ 感叹号! 点. 星号* 管道符号| 右括号) 等

36.\. 转义为点字符(点字符在正则表达式中可以匹配任意字符)

37./* 零个或多个正斜杠

38..* 零个或多个任意字符(即,匹配任意字符串,包括空字符)

39.^$ 匹配"空字符"、"空行"

40.^.*$ 匹配任意字符串(仅限一行)

41.[^/.] 匹配既非"正斜杠"也不是"点"的任意字符

42.[^/.]+ 匹配第一个字符既非"正斜杠"也不是"点",后继字符可以是"正斜杠"或者"点"的字符串

43. https:// 匹配" https:// "

44.^domain.* 匹配以"domain"开始的字符串

45.^domain\.com$ 仅匹配"domain.com"

46.-d 测试字符串是否是已存在的目录

47.-f 测试字符串是否是已存在的文件

48.-s 测试字符串所指文件是否有"非零"值

HTTP协议重定向编码

·301  Moved Permanently

·302  Moved Temporarily

·403  Forbidden

·404  Not Found

·410  Gone