10
Aug
6

Symfony 1.2 redirect specific modules and actions to HTTPS (SSL)

Post Symfony 1.1, the sfSslRequirementPlugin will no longer work.

Having needed a way to force a SSL connection for certain pages, I modified a few scripts that I found online, and created a very simple filter to handle this. This was inspired by this script, and the unacceptably poor example in the Symfony 1.2 book.

To start off with, we need to modify our app.yml file to specify what modules and/or actions need to be secure. Leave the action completely blank if you want the entire module secure. Also change ignore_non_secure to true if you don’t care if non specified pages are server over a ssl connection. Basically, from the app.yml below, setting this to false, will redirect any module/action to the non-secure version if it is not specifically defined under secure_actions. Setting it to true will allow a user to request any page over https, even if it is not listed in app.yml. Let me know if this is confusing in any way.

//app.yml
all:
  ssl:
    ignore_non_secure: false
    secure_actions:
      - { module: shopping_cart}
      - { module: services  action: apply}

Next we add this filter. Save this under MyProject/apps/MyApp/lib/sfSslFilter.php

<?php
 
class sslFilter extends sfFilter
{
    /**
    * Execute filter
    *
    * @param FilterChain $filterChain The symfony filter chain
    */
    public function execute ($filterChain)
    {
 
        $context = $this->getContext();
        $request = $context->getRequest();
 
        $ssl_actions = sfConfig::get('app_ssl_secure_actions');
        $allow_ssl = sfConfig::get('app_ssl_ignore_non_secure');
 
        if (!$request->isSecure())
        {
            //Redirect to the Secure Url
            //If the module and/or action match $ssl_actions set in app.yml
            foreach($ssl_actions as $action)
            {
 
               if($action['module'] == $context->getModuleName() && !$action['action']){
 
                    //The entire module needs to be secure
                    //Redired no matter what the action is.
 
                    $secure_url = str_replace('http', 'https', $request->getUri());
                    return $context->getController()->redirect($secure_url, 0 , 301);
 
 
                } else if($action['module'] == $context->getModuleName() && $action['action'] == $context->getActionName())
                {
 
                    //Redirect if the module and action need to be secure
 
                    $secure_url = str_replace('http', 'https', $request->getUri());
                    return $context->getController()->redirect($secure_url, 0 , 301);
                }
             }
 
        } else if($request->isSecure() && !$allow_ssl)
        {
            $redirect = true;
 
            //Redirect to the Non-Secure Url
            //If the module and/or action are not in $ssl_actions set in app.yml
            foreach($ssl_actions as $action)
            {
                if(($action['module'] == $context->getModuleName() && !$action['action']) || ($action['module'] == $context->getModuleName() && $action['action'] == $context->getActionName()))
                {
                    $redirect = false;
                }
            }
 
            if($redirect)
            {
                 $non_secure_url = str_replace('https', 'http', $request->getUri());
                 return $context->getController()->redirect($non_secure_url, 0 , 301);
            }
        }
 
        $filterChain->execute();
 
    }
}

Finally, add to the MyProject/apps/MyApp/config/filters.yml file:

sslFilter:
  class:  sslFilter

Clear the cache (symfony cc), and there you have it. Let me know if you have a better or different way of dealing with this on a per-module or per-action basis. Hopefully sfSslRequirementPlugin will get ported to work with Symfony 1.2, as the method above will not alter routes on your application.

Additionally, I specifically used 301 redirects to make this more search engine friendly, in case Google or another bot gets on a ssl page. This will help prevent getting duplicate pages indexed due to http and https versions of the same page.

Enjoyed reading this post?
Subscribe to the RSS feed and have all new posts delivered straight to you.
6 Comments:
  1. stunami 11 Aug, 2009

    Hi,

    There is a branch for 1.2 of sfSslRequirementPlugin. The code is probably fine, (though I haven’t tried it) it just needs a version for 1.2 to be rolled and released

    http://trac.symfony-project.org/browser/plugins/sfSslRequirementPlugin/branches/1.2

    Probably worth a go

  2. jestep 11 Aug, 2009

    I’m pretty sure that is in reference to sfSslRequirementPlugin 1.2, and not Symfony 1.2.

    Looking at the Release track, it shows Symfony 1.0 and 1.1 support. I did try v2.0 and is did not work properly on Symfony 1.2. It may be possible to modify it to get it to work properly without too much trouble.

  3. stunami 12 Aug, 2009

    Oh right. As you say maybe worth investigating as I don’t see why anything would of changed in 1.2 to break it fundamentally

  4. […] code I wrote It is based off of Say No To Flash’s filter that they wrote, however I was generally displeased with their method. It loops over […]

  5. Graham Christensen 1 Sep, 2009

    I wrote an alternative to this that has a slightly more efficient processing system, and is a bit easier to understand. The two loops in this case are a little bit over-complicated, and easy to replace with at touch of logic.

    Forcing SSL in Symfony 1.2 – I Am Graham

  6. Kenneth 8 Sep, 2010

    Thanks for this – works a treat!

    There’s a comma missing at line 7 of the app.yml insert:
    – { module: services, action: apply}

Copyright © 2024 SayNoToFlash, Jamie Estep, All Rights Reserved · Theme design by Themes Boutique