09 Jan 2015
# 虚机配置 <VirtualHost *:80> ServerName www.example.com DocumentRoot "/var/www/html" CustomLog "logs/server0_vhost_log" combined <Directory "/var/www/html"> <RequireAll> Require all granted </RequireAll> </Directory> </VirtualHost>
# 编辑主配文件,加载rewrite模块 LoadModule rewrite_module modules/mod_rewrite.so # 重载服务配置,检查模块加载情况 apachectl graceful apachectl -M |grep rewrite rewrite_module (shared)
# 虚拟主机中重定向配置 <IfModule mod_rewrite.c> RewriteEngine on RewriteCond %{HTTP_HOST} ^bbs.example.com$ RewriteRule ^/(.*)$ http://www.example.com/$1 [R=301,L] </IfModule> # 重载服务配置,检查重定向结果 apachectl graceful curl -x localhost:80 bbs.example.com -I HTTP/1.1 301 Moved Permanently Date: Wed, 25 May 2016 14:26:12 GMT Server: Apache/2.4.20 (Unix) PHP/5.6.21 Location: http://www.example.com/ Content-Type: text/html; charset=iso-8859-1
RewriteRule的正则知识
官网链接: http://httpd.apache.org/docs/2.4/rewrite/intro.html


## 访问bbs.example.com时,根据后面是纯数字或纯字母做出反应 # RewriteEngine on # RewriteCond %{HTTP_HOST} ^(http://)?bbs.example.com # RewriteRule ^/([0-9]+)$ http://www.example.com/first$1 # RewriteRule ^/([0-9]+)$ http://www.example.com/second$1 # RewriteRule ^/([a-z]+)$ http://www.example.com/third$1 # RewriteRule ^/(.*)$ http://www.example.com/fourth$1 ## 通过下面的三次测试可以得出以下结论 ## 当RewriteCond条件匹配到的情况下 # 匹配到的位置最上面的rule生效 ## 当RewriteCond条件不匹配的情况下 # 跳过第一条rule,匹配到的最上面的rule生效 # RewriteCond匹配,三条rule匹配,上面的生效 curl -x localhost:80 bbs.example.com/11 -I HTTP/1.1 302 Found Date: Thu, 26 May 2016 14:25:29 GMT Server: Apache/2.4.20 (Unix) PHP/5.6.21 Location: http://www.example.com/first11 Content-Type: text/html; charset=iso-8859-1 # RewriteCond匹配,若只有一条rule匹配,该rule生效 curl -x localhost:80 bbs.example.com/aa1 -I HTTP/1.1 302 Found Date: Thu, 26 May 2016 15:33:50 GMT Server: Apache/2.4.20 (Unix) PHP/5.6.21 Location: http://www.example.com/fourthaa1 Content-Type: text/html; charset=iso-8859-1 # RewriteCond不匹配时,因为第4条rule匹配到,该rule生效 # 但当我测试将第4条rule换去第一条,未生效 curl -x localhost:80 www.baidu.com -I HTTP/1.1 302 Found Date: Thu, 26 May 2016 15:26:00 GMT Server: Apache/2.4.20 (Unix) PHP/5.6.21 Location: http://www.example.com/fourth Content-Type: text/html; charset=iso-8859-1

<IfModule mod_rewrite.c> RewriteEngine on RewriteCond %{REQUEST_URI} ^.*/tmp/* [NC] RewriteRule .* - [F] </IfModule> ## 条件: 当request请求的url中包含/tmp/时 ## NC: 判断条件不区分大小写 ## RewriteRule中的"-"代表什么都不做 ## F: 拒绝访问
user_agent是什么?
user_agent就是访问网络的工具(浏览器),因为user是通过浏览器和server沟通的,所以浏览器就是user的agent
目前,一方面浏览器基本都通过给server发送一条user agent字符串,来告诉server自己的访问信息;另外一方面,搜索引擎(google、baidu)在放出网络爬虫来收集网站link时,网络爬虫也会发送user agent字符串来表明自己的身份。
user_agent string
此图来自网络http://whatsmyuseragent.com/WhatsAUserAgent

# rewrite写法 <IfModule mod_rewrite.c> RewriteEngine on RewriteCond %{HTTP_USER_AGENT} ^*Firefox/4.0* [NC,OR] RewriteCond %{HTTP_USER_AGENT} ^*Tomato Bot/1.0* [NC] RewriteRule .* - [F] </IfModule> # 不推荐用rewrite到404,会产生死循环
# 原意是把所有访问请求rewrite到/111/$1 RewriteRule ^(.*) /111/$1 [R,L] # 但当访问类似于www.111.com/111,它就会无限循环在网址后面增加111 # 为了避免死循环产生,可以按如下方法处理 RewriteCond %{REQUEST_URI} !^/111 RewriteRule ^(.*) /111/$1 [R,L]
# 使用rewrite flags - [E=var:varvalue] RewriteCond %{HTTP_HOST} ^(www\.)?([a-z0-9-]+)\.example\.com [NC] RewriteRule .? - [E=Wa:%1,E=Wb:%2] RewriteRule ^(.*?)-([a-z]+) %{ENV:Wb}/$1.%{ENV:Wb} [L] RewriteRule ^(.*?)-([0-9]+)([a-z]) %{ENV:Wb}/$1$3.$2 [L] # 将RewriteCond的%1和%2赋值给变量 # rewrite flag [L]含义是last,代表此规则是最后一条规则;
# 当访问非bbs.example.com时,跳过3行Rule # 当访问bbs.example.com时,因为不匹配条件,跳至第二行rule # 根据第二行rule规则,跳过第三行,执行第四行规则 RewriteEngine on RewriteCond %{HTTP_HOST} !bbs.example.com RewriteRule .? - [S=3] RewriteRule .? - [S=1] RewriteRule ^/(.*)$ http://bbs.example.com/$1s RewriteRule ^/(.*)$ http://bbs.example.com/$1f # 验证结果 curl -x localhost:80 bbs.example.com -I HTTP/1.1 302 Found Date: Thu, 26 May 2016 11:03:51 GMT Server: Apache/2.4.20 (Unix) PHP/5.6.21 Location: http://bbs.example.com/f Content-Type: text/html; charset=iso-8859-1
某些场景下,为了安全,只会开放特定的HTTP请求方法,其余的全部禁用掉。
下面的配置示例,禁用了除GET和POST之外的所有请求方法,并返回405状态码
RewriteEngine On RewriteCond %{REQUEST_METHOD} !^(GET|POST) RewriteRule .* - [R=405]
在一些安全类的认证中,比如PCI-DSS,对网站加载资源的来源要求是十分严格的。比如说,a.com的站点加载了b.com的资源,那么就必须要求a.com所属的组织,对b.com加载的资源要有可控性。这种可控性可以使用两种方式实现,1是把资源文件拿到a.com的服务器上,使用自己的域名来提供响应,那么就做到了完全可控;2是在a.com上对b.com的资源进行加载时,对其版本进行校验,确保这个资源的版本是经过审核无篡改的,防止b.com通过更新夹杂一些私货。
上面的安全措施是完全可以理解的,但一般如果考虑到a.com和b.com背后的组织之间的协调性,#2这个方案是更加合适的。但是实现#2的时候需要等开发排期,那么临时是否可以在基于对b.com提供的资源的基本信任的前提下,临时让访问a.com的时候,假装看不到b.com的资源了呢?
其实是有方案的,就是相当于之前客户访问a.com的时候,返回的资源中告诉用户,你还需要去b.com拿一个资源。改造为,客户访问a.com的时候,a.com所属的服务器充当一个代理服务器,帮用户请求b.com来把资源请求到,然后转发给客户,以造成一种客户只访问了a.com资源的假象。
落实到具体的实现上来说,就是需要配置apache,来通过rewrite实现浏览器中url不变的一个效果。这里就可以通过rewrite中的P这个flag来实现了,P的含义是,rewrite时,将服务器转进proxy模式,来代理客户拿到资源,再通过本机返回给用户。这就是为什么需要同时引入rewrite和proxy_http两个包的原因。
# 主配置中,加载rewrite和proxy相关的模块 LoadModule rewrite_module modules/mod_rewrite.so LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http_module modules/mod_proxy_http.so LoadModule proxy_http2_module modules/mod_proxy_http2.so # 虚拟主机配置中,使用"P"Flag来将rewrite通过proxy的方式请求回来 RewriteEngine On RewriteCond %{REQUEST_URI} ^/path/to/some.js$ RewriteRule "^(.*)$" "http://www.bbb.com/path/to/some.js" [P]