通过 Apache 配置 Rewrite 实现网络服务的 co-branding

红薯 发布于 2010/02/21 11:26
阅读 656
收藏 3

什么是 co-branding

时下,很多网站以网络服务的方式为企业用户提供“托管”服务(Hosting),典型的应用比如 Gmail 邮箱托管服务。如果你有一个公司叫做 data.com, 你可以通过 Gmail 注册自己公司的邮箱域名,并且访问以下链接到公司邮箱域名 : https://www.google.com/a/data.com。

并且在这个带有自己公司域名的页面下,可以创建自己的邮箱,例如 admin@data.com。注意这个邮箱地址是没有 gmail.com 的。因此,对于中小企业来说,这种托管邮箱服务就仿佛像提供了一个物理上的属于自己公司的邮件服务器并且用的也是自己公司的域名。而这种服务实际上是在 google 云服务端通过托管服务实现的。另一方面,基于商业形象的考虑,很多中小公司在使用便宜或者免费的托管服务时,还希望用上自己公司的 LOGO 或者名称,比如上面 Gmail 的例子,通过上述链接进入的页面,可以显示上用户公司的名称和标志,从而使得用户对外洽谈的客户也感觉就像访问了用户公司自己的邮箱服务,我们把这种由托 管服务衍生出来的用户需求叫做“web service co-branding”,即网络服务的品牌联合。

Co-branding 的主要需要解决的问题就是通过用户访问的不同 URL 来识别用户是想访问哪个品牌 (brand) 下的网络服务,从而将之后有关品牌的文字,图片,LOGO,Flash 等等界面布局相关的要素都用上该品牌下提供的 UI 要素,甚至包括网页布局。当然这种基于品牌定制化的服务是客户在网络服务提供商购买或者免费获得的。

本文主要讲解了一种实现这种定制化服务的技术手段。本文假设用户都已经熟悉开发网络服务的一些软件和技术:Apache,是 Apache 软件基金会的一个开放源码的网页服务器,可以在大多数计算机操作系统中运行,由于其跨平台和安全性被广泛使用,是最流行的 Web 服务器端软件之一; JSP(全称 JavaServer Pages)是由 Sun Microsystems 公司倡导和许多公司参与共同建立的一种使软件开发者可以响应客户端请求,而动态生成 HTML、XML 或其他格式文档的 Web 网页的技术标准。JSP 技术是以 Java 语言作为脚本语言的,JSP 网页为整个服务器端的 Java 库单元提供了一个接口来服务于 HTTP 的应用程序。本文的网页例子用 JSP 实现,当然读者也可以轻松的想到如何用 PHP 或者其他网页开发语言来实现例子中的功能。

本文包括三部分:Apache 配置和 URL 跳转、JSP 提取和保存 branding 信息、JSP 动态显示不同的 UI 元素。

Apache 配置和 URL 跳转

前面介绍过,Co-branding 需要解决的首要问题就是如何通过用户访问的不同 URL 来识别用户是想访问哪个品牌 (brand) 下的网络服务。为了解决这个问题,有一种技术手段就是想到利用 Apache 服务器,Apache 服务器监听着服务域的 HTTP 端口,当用户访问 http://www.CRL.com/mycompany.com 网络服务的时候,用户的浏览器会首先将请求发送到 Apache 服务器,然后 Apache 服务器分发给处理该请求的模块和最后返回用户应该看到的页面到用户端的浏览器。因此,我们利用 Apache 的 rewrite module,就可以做到当收到用户的 URL 请求时候,识别出用户是想访问 mycompany.com 品牌的网络服务,然后将请求转换成带有品牌信息的 URL 转发给特定的处理页面。

  1. 首先确定您使用的 Apache 版本,及是否加载了 mod_rewrite 模块。及是否加载了 mod_rewrite 模块 . mod_rewrite 的是一个 Apache 模块,可使服务器操纵请求的网址。根据一系列规则对传入的网址进行检查,规则中包含一个正则表达式来检测特定的格式。 如果在地址中发现了一个格式,并且满足适当的条件,该格式就会被一个替代的字符串或者是动作取代。

Apache 1.x 的用户请检查 conf/httpd.conf 中是否存在如下两段代码:


清单 1. Apache 1.x 的加载模块代码

				 
LoadModule rewrite_module libexec/mod_rewrite.so
AddModule mod_rewrite.c

 

Apache 2.x 的用户请检查 conf/httpd.conf 中是否存在如下一段代码:


清单 2. Apache 2.x 的加载模块代码

				 
LoadModule rewrite_module modules/mod_rewrite.so

 

如果存在,那么在配置文件(通常就是 conf/httpd.conf)中加入如下代码。此时请务必注意,如果网站使用通过虚拟主机来定义,请务必加到虚拟主机配置,即 <VirtualHost> 中去,如果加在虚拟主机配置外部将可能无法使用,改好后将 Apache 重启。稍后再解释这段代码的意思


清单 3. 加入配置文件的代码

				 
LoadModule rewrite_module modules/mod_rewrite.so
<IfModule rewrite_module>
RewriteEngine on
RedirectMatch ^(.*)/([^/]*)\.com$ $1/index.jsp?brand=$2
</IfModule>

 

如果没有加载这个 mod_rewrite 模块,那多半就是 Apache 本身编译的时候就没有编译上 rewrite 模块了,那我们需要手工自己编译一下这个模块。

先找到你的 Apache 最初编译的源代码目录,找到放 mod_rewrite.c 的目录,例如 :/usr/local/src/httpd-2.2.13/modules/mappers, 然后使用 Apache 安装好的 apxs 命令编译即可:


清单 4. 指向源代码目录的代码

				 
/usr/local/apache2/bin/apxs -i -a -c ./mod_rewrite.c

 

编译的过程如下:


清单 5. 编译过程的代码

				 
/usr/local/apache2/build/libtool --silent --mode=compile gcc -prefer-pic 
 -DAP_HAVE_DESIGNATED_INITIALIZER -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -g -O2 -pthread
-I/usr/local/apache2/include  -I/usr/local/apache2/include 
 -I/usr/local/apache2/include  -c -o ./mod_rewrite.lo
./mod_rewrite.c && touch ./mod_rewrite.slo
/usr/local/apache2/build/libtool --silent --mode=link gcc -o ./mod_rewrite.la 
 -rpath /usr/local/apache2/modules -module -avoid-version   
 ./mod_rewrite.lo
/usr/local/apache2/build/instdso.sh SH_LIBTOOL='/usr/local/apache2/build/libtool'
./mod_rewrite.la /usr/local/apache2/modules
/usr/local/apache2/build/libtool
--mode=install cp ./mod_rewrite.la /usr/local/apache2/modules/
cp ./.libs/mod_rewrite.so /usr/local/apache2/modules/mod_rewrite.so
cp ./.libs/mod_rewrite.lai /usr/local/apache2/modules/mod_rewrite.la
cp ./.libs/mod_rewrite.a /usr/local/apache2/modules/mod_rewrite.a
chmod 644 /usr/local/apache2/modules/mod_rewrite.a
ranlib /usr/local/apache2/modules/mod_rewrite.a
PATH="$PATH:/sbin" ldconfig -n /usr/local/apache2/modules
----------------------------------------------------------------------
Libraries have been installed in:
  /usr/local/apache2/modules

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
  - add LIBDIR to the `LD_LIBRARY_PATH' environment variable
    during execution
  - add LIBDIR to the `LD_RUN_PATH' environment variable
    during linking
  - use the `-Wl,--rpath -Wl,LIBDIR' linker flag
  - have your system administrator add LIBDIR to `/etc/ld.so.conf'

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------
chmod 755 /usr/local/apache2/modules/mod_rewrite.so
[activating module `rewrite' in /usr/local/apache2/conf/httpd.conf]

 

如果没有什么错误的话,会在 apache/modules 目录中编译出一个 mod_rewrite.so 文件。
同时 apxs 应该会自动编译并且部署到你的 Apache 目录,会在
vi /usr/local/apache2/conf/httpd.conf 里加载:
LoadModule rewrite_module    modules/mod_rewrite.so

如果没有部署,你将 mod_rewrite.so 手工拷贝到的 Apache modules 目录下并且修改 httpd.conf 进行加载即可,例如:/usr/local/apache2/modules

2. 接下来就可以用 rewrite 来将不同的访问 URL 参数化来处理了。Rewrite module 可以用一个正则表达式来匹配用户发送过来的 URL 请求,然后转换成另外一种形式的 URL 请求,然后再交给 Apache 去分发和处理修改后的 URL 页面请求。

我们在 Apache 的 httpd.conf 里加入以下的 code 就可以达到这样的效果。


清单 6. URL 转换的代码

				 
LoadModule rewrite_module modules/mod_rewrite.so
<IfModule rewrite_module>
RewriteEngine on
RedirectMatch ^(.*)/([^/]*)\.com$ $1/index.jsp?brand=$2
</IfModule>

 

熟悉正则表达式的读者,可以看到例子中的 RedirectMatch 后面跟的正则表达式会匹配 http://www.CRL.com/mycompany.com 然后转换为 http://www.CRL.com/index.jsp?brand=mycompany


图 1. 流程图
图 1. 流程图

JSP 提取和保存 branding 信息

熟悉 JSP 的朋友知道,转换以后的 URL http://www.CRL.com/index.jsp?brand=mycompany, 已经将 mycompany 作为一个参数 brand, 传递给了 index.jsp(通常一个 jsp 网站的首页)。而 index.jsp 拿到这个参数以后,就可以提取出 branding 信息。举个 index.jsp 的例子:


清单 7.branding 信息传递和提取过程代码

				 
<%@page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>
<%
String brand = request.getParameter("brand");
if (brand == null)
brand = "";
session.setAttribute("brand", brand);
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional // EN"
"http://www.w3.org/TR/xhtml/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title><%= brand%></title>
</head>
<body>
</body>
</html>

 

例中,String brand = request.getParameter("brand"); 此句将取得”mycompany”这个值。这样我们就提取出了 branding 信息。

提取出了 branding 信息之后,我们还要保存 branding 信息以便用户访问网站的任何网页的时候,网页都能根据 branding 信息显示不同的品牌 UI. 为了保存 branding 信息,我们有多种选择。一种是将 branding 信息提取出来以后保存在服务器端的 Session 对象中,这样用户访问别的页面的时候,branding 信息会随着 session 保存着。session 只要没有失效,这个信息都会保存在服务器端,用户访问页面的时候,服务器就自动取得了 branding 信息了。另外一种方法也可以把 branding 信息保存在用户客户端的浏览器的 cookie 里。Cookie 也是一种可以帮助长久保存用户的使用信息的方法。例中,我们采用了服务器端 Session 对象保存用户请求 branding 的信息的方法。即是这一行代码作的事情:

session.setAttribute("brand", brand);

JSP 动态显示不同的 branding UI 元素

在首页保存下来 branding 信息,网站其他各个网页就可以随时从 session 或者 cookie 中提取 branding 信息了。然后根据不同的 branding 使用统一风格的品牌标示元素,。

例如,首页有个链接到 news.jsp,news.jsp 里代码如下 :


清单 8. 提取 branding 并动态显示的代码

				 
<%@page contentType=”text/html;charset=”UTF-8” pageEncoding=”UTF-8”%>
<%
String brand = (String)session.getAttribute("brand");
String logoPath = brand + “/logo.gif”;
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional // EN"
"http://www.w3.org/TR/xhtml/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title><%= brand%></title>
</head>
<body>
<div id="popheader"
background = 'url(' + '<%= logoPath%>' + ')';></div>
</body>
</html>

 

在例子中,从 session 中提取 branding 信息的代码就是这一行:

String brand = (String)session.getAttribute("brand");

网站标题因此可以换成 branding 里的公司名字:

<title><%= brand%></title>

也可以通过 brand + “/” + logo.gif 这样的方式来访问 Apache 服务器上不同公司目录下的 LOGO 图标,显示在网站上 :

<div id="popheader" background = 'url(' + '<%= logoPath%>' + ')';></div>

对于此文来说,我们 branding 用的是 mycompany,那么显示的图片应该就是 mycompany/logo.gif.

自此,网络服务的 co-branding UI 从技术上就已经实现了,剩下的就是用户需要设计自己自定义的 UI 元素了。


图 2. 贴牌界面 1
图 2. 贴牌界面 1

图 3. 贴牌界面 2
图 3. 贴牌界面 2

最后,提醒读者最好也处理从 session 对象中读不出 branding 信息的情况。例如 brand 为 null 或者 empty string 的时候也显示一套默认的 UI 要素,使得用户就用 www.CRL.com 访问能看到你的网络服务默认的 UI 样式。通常这是你作为网络服务提供商自己本身的品牌 UI。

结束语

本文讨论了如何利用 Apache 的 rewrire module,重写 URL 将 branding 信息变成 JSP 页面请求的参数,再通过 JSP 对于 session 对象的操作来保存和提取用户的 brand 信息,最后显示自定义的 UI 的技术方案来实现网络托管服务中的 co-branding 用户需求。

加载中
返回顶部
顶部