学习 yii 框架 - 安全站点和非安全站点的 URL 管理

在本文中我将描述怎么管理安全站点和非安全站点的 URL 管理。

安全站点的内容使用 https SSL (安全套接字层) 协议发送,而非安全站点使用 http 协议。为了描述简单,我们称前者 https 内容/页,后者 'http' 内容/页。一个严格要求的网站通常需要一些页面使用 https ,一些页面使用 http。例如,为了防止密码嗅探,我们的登录页面使用 https,而为了减轻服务器压力,对于不敏感的页面(例如,主页)我们使用 http

当我们在 https 页面是我们会需要生成 http 页面 URL,反之亦然。例如,一个站点有一个所有页面都使用的主菜单,主菜单中包含有,https (例如;登录页) 和 http(例如:关于页) 的链接。如果我们在一个 http 页面,我们可以直接链接到其他 http 页面(例如: /about),但是我们不得不使用绝对URL地址使用 https 协议链接到其他 https 页面。同上如果我们在 https 页面,我们也会遇到类似的情况。

另一种情况是我们使用 http 协议请求也安全页面,我们应当将浏览器重定向到使用 https 协议,反之亦然。重定义通常为 301 永久重定向。这可能使用 web 服务器的重写规则实现。但是如果我们要细化安全和非安全的页面,重写规则可能会变得非常复杂。

为了实现上面的两个需求,我们可以继承 CUrlManager, 如下

class UrlManager extends CUrlManager
{
	/**
	 * @var string 非SSL模式下的主机信息
	 */
	public $hostInfo = 'http://localhost';
	/**
	 * @var string SSL模式下的主机信息
	 */
	public $secureHostInfo = 'https://localhost';
	/**
	 * @var array 只在 SSL 模式下可用的路由列表.
	 * 数组的每一项既可以是一个 URL 路由(例,'site/create')
	 * 也可以是控制器 ID (例,'settings').后者表示该控制器所有动作都为安全页
	 */
	public $secureRoutes = array();
	
	public function createUrl($route, $params = array(), $ampersand = '&')
	{
		$url = parent::createUrl($route, $params, $ampersand);
		
		// 如果已经为 绝对 URL 直接返回
		if (strpos($url, 'http') === 0) {
			return $url;  
		}
		
		// 检查当前协议是否是预期的协议
		// 如果不是则需要在生成 URL 时使用正确的主机信息
		$secureRoute = $this->isSecureRoute($route);
		if (Yii::app()->request->isSecureConnection) {
			return $secureRoute ? $url : $this->hostInfo . $url;
		} else {
			return $secureRoute ? $this->secureHostInfo . $url : $url;
		}
	}

	public function parseUrl($request)
	{
		$route = parent::parseUrl($request);
		
		// 如果当前协议不符合预期协议,执行 301 重定向
		$secureRoute = $this->isSecureRoute($route);
		$sslRequest = $request->isSecureConnection;
		if ($secureRoute !== $sslRequest) {
			$hostInfo = $secureRoute ? $this->secureHostInfo : $this->hostInfo;
			if ((strpos($hostInfo, 'https') === 0) xor $sslRequest) {
				$request->redirect($hostInfo . $request->url, true, 301);
			}
		}
		return $route;
	}

	private $_secureMap;

	/**
	 * @param string 需要检查的 URL 路由
	 * @return boolean 给出的 URL 路由是否应该在 SSL 模式下
	 */
	protected function isSecureRoute($route)
	{
		if ($this->_secureMap === null) {
			foreach ($this->secureRoutes as $r) {
				$this->_secureMap[strtolower($r)] = true;
			}
		}
		$route = strtolower($route);
		if (isset($this->_secureMap[$route])) {
			return true;
		} else {
			return ($pos = strpos($route, '/')) !== false 
				&& isset($this->_secureMap[substr($route, 0, $pos)]);
		}
	}
}

现在,在应用程序的配置,我们应当使用我们的 URL 管理器来取代默认。

return array(
    // ....
    'components' => array(
        'urlManager' => array(
            'class' => 'UrlManager',
            'urlFormat' => 'path',
            'hostInfo' => 'http://example.com',
            'secureHostInfo' => 'https://example.com',
            'secureRoutes' => array(
            	'site/login',   // site/login action
            	'site/signup',  // site/signup action
            	'settings',     // all actions of SettingsController
            ),
        ),
    ),
);

在上面的代码中,我们配置了 urlManager 登录、注册和所有设置页面为安全页面。如果,你想添加其他页面,只需向 secureRoutes 数组中添加相应内容。

现在我们可以像往常一样使用 Yii::app()->createUrl() 方法来创建 URL 地址。我们的 urlManager 会自动确定是否需要加上合适的前缀,如果需要的话,url 管理器也会执行 301 重定向。

英文原文

转载于:https://my.oschina.net/moonshadow/blog/88844

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值