一、 .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.[^/.]+ 匹配第一个字符既非"正斜杠"也不是"点",后继字符可以是"正斜杠"或者"点"的字符串
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