Yii 1.1: URL management for Websites with secure and nonsecure pages


In this article, I will describe how to manage URLs for a Website that has both secure and nonsecure content.

Secure content are sent via the https protocol using SSL (secure socket layer), while nonsecure content via the normal http protocol. For simplicity of description, let's call the former https content/page while the latter http content/page. A serious Website often needs to serve some pages in https and some in http. For example, to prevent password sniffing, we would like to serve the login page using https; and to save server processing power, we would like to serve insensitive content (e.g. home page) using http.

A requirement is that when we are in an https page we want to generate URLs to http pages, and vice versa. For example, a Web site has a main menu shared by all pages, and the main menu contains links to both http page (e.g. About page) and https page (e.g. Login page). If we are now in an http page, we can use relative URLs (e.g. /about) to link to other http pages, but we have to use absolute URLs with https protocol to link to the https pages. And if we are in an https page, the situation will be the other way around.

Another requirement is that if a secure page is requested via an http request, we should redirect the browser to use https protocol; and vice versa. The redirection usually should be 301 permanent redirection. It is possible to achieve this goal via the rewrite rules of Web servers. But the rewrite rules could become very complex if we want fine-grained control of secure and nonsecure content.

To achieve the above two requirements, we can extend CUrlManager as follows,

class UrlManager extends CUrlManager
     * @var string the host info used in non-SSL mode
    public $hostInfo = 'http://localhost';
     * @var string the host info used in SSL mode
    public $secureHostInfo = 'https://localhost';
     * @var array list of routes that should work only in SSL mode.
     * Each array element can be either a URL route (e.g. 'site/create') 
     * or a controller ID (e.g. 'settings'). The latter means all actions
     * of that controller should be secured.
    public $secureRoutes = array();
    public function createUrl($route, $params = array(), $ampersand = '&')
        $url = parent::createUrl($route, $params, $ampersand);
        // If already an absolute URL, return it directly
        if (strpos($url, 'http') === 0) {
            return $url;  
        // Check if the current protocol matches the expected protocol of the route
        // If not, prefix the generated URL with the correct host info.
        $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);
        // Perform a 301 redirection if the current protocol 
        // does not match the expected protocol
        $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 the URL route to be checked
     * @return boolean if the give route should be serviced in SSL mode
    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)]);

Now in the application configuration, we specify UrlManager as our URL manager instead of the default CUrlManager:

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

In the above code, we configure UrlManager to secure the login, sign-up and settings pages. If you want to secure other pages, just add the corresponding routes to the secureRoutes array shown above.

We can now use Yii::app()->createUrl() as usual in places where we need to create URLs. Our UrlManager will automatically determine if the generated URLs need to be prefixed with proper host info. The UrlManager will also do the 301 redirection work if needed.

Total 12 comments

#19566 report it
oligalma at 2015/09/09 11:07am

This article solved the https problems of my website. Really helpful!!!

#19160 report it
avner at 2015/03/30 06:40pm
Bug with modules - and a fix

In case of a url which is www.example.com/module/controller/action/arg1/arg1val

adding "module/controller" to the $secureRoutes won't work as expected.

The fix is, in function isSecureRoute(), replace the line

return ($pos = strpos($route, '/')) !== false 
                && isset($this->_secureMap[substr($route, 0, $pos)]);

with the lines

if (($pos = strpos($route, '/')) !== false 
&& isset($this->_secureMap[substr($route, 0, $pos)])) return true; //match controler/*
            return (($pos = strpos($route, '/', $pos+1)) !== false 
&& isset($this->_secureMap[substr($route, 0, $pos)])); //match module/controller/*
#18108 report it
sandro1111 at 2014/09/09 07:52am
Good explanation but VERY BAD realization in yiiframework.com

I like the explanation in this article but why the hell is the yiiframework.com login not realized using https? The form is submitted using plain text (http). I know this is probably not the best place to tell this bug but I hope it can be fixed using this article ;-)

#17421 report it
maxtorchel at 2014/06/09 11:57am

can i set hostInfo and secureHostInfo to relative url (without domain name)? I wont to set one site to different domains.

#16288 report it
tpandi at 2014/02/06 08:42am
SSL needs


I am new in yii . I don't know how to use the UrlManager class. Kindly explain brifly

#15362 report it
prazi at 2013/11/01 02:44am
Spot On

Thanks vey much. This was exactly what I wanted. Worked like a charm. Cheers.

#14477 report it
HermesCK at 2013/08/15 06:37am

Many thanks Qiang ... perfect and simple solution

#14265 report it
nguyendh at 2013/07/30 07:28pm
awesome trick

Thanks so much Qiang

Saving me tons of trouble working with Apache ReWrite.

#13690 report it
M0ka at 2013/06/17 11:55am
Nice article

Thanks a lot

#13582 report it
Hasan Tokatlı at 2013/06/08 03:30am
How to force all routes to https?

Thanks for the article. This is an essential wiki.

My customer wanted me to serve all pages via https protocol. So using this wiki I added all of the sites controllers in


array. (site route too) Is this solution effective for making all routes secure? Thanks.

#10348 report it
Antonio Ramirez at 2012/10/22 04:21am
Nice one

Thanks Qiang... very good article.

#10341 report it
bonnie at 2012/10/21 08:19am
Nice article

Thanks for this article. This is what I was wondering how to do it in my project am working on.

Leave a comment

Please to leave your comment.

Write new article
  • Written by: qiang
  • Category: How-tos
  • Yii Version: 1.1
  • Votes: +29 / -1
  • Viewed: 39,751 times
  • Created on: Oct 19, 2012
  • Last updated: Oct 20, 2012
  • Tags: URL