views:

1089

answers:

1

Is anyone successfully using both the Authorize and RequireSSL (from MVC futures) attributes together on a controller? I have created a controller for which I must enforce the rule that the user must be logged in and using a secure connection in order to execute. If the user is not on a secure connection, I want the app to redirect to https, thus I am using Redirect=true on the RequireSSL attribute. The code looks something like (CheckPasswordExpired is my homegrown attribute):

[Authorize]
[RequireSsl(Redirect = true)]
[CheckPasswordExpired(ActionName = "ChangePassword",
    ControllerName = "Account")]
[HandleError]
public class ActionsController : Controller
{
    ....
}

mysite.com/Actions/Index is the default route for the site and also the default page to redirect to for forms authentication.

When I browse to http://mysite.com, what I want to get is the user redirected to a secure connection, and because they are not authenticated yet, to the login page. What I get is an HTTP 400 error (Bad Request). If I navigate to http://mysite.com/Account/Login, the redirect works, but neither my Account controller nor Login action method have the [Authorize] attribute.

Anyone have any experience with using these two attributes together to achieve my objective?

Thanks!

+3  A: 

I'm using both of them with success. Do you have the attributes on your default action?

public class HomeController : BaseController
{
  [Authorize]
  [RequireSsl]
  public ActionResult Index ()
  {
  }
}

BTW I'm using a slightly modified version than the futures so that I can disable SSL globally:

[AttributeUsage (AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public sealed class RequireSslAttribute : FilterAttribute, IAuthorizationFilter
{
 public RequireSslAttribute ()
 {
  Redirect = true;
 }

 public bool Redirect { get; set; }

 public void OnAuthorization (AuthorizationContext filterContext)
 {
  Validate.IsNotNull (filterContext, "filterContext");

  if (!Enable)
  {
   return;
  }

  if (!filterContext.HttpContext.Request.IsSecureConnection)
  {
   // request is not SSL-protected, so throw or redirect
   if (Redirect)
   {
    // form new URL
    UriBuilder builder = new UriBuilder
    {
     Scheme = "https",
     Host = filterContext.HttpContext.Request.Url.Host,
     // use the RawUrl since it works with URL Rewriting
     Path = filterContext.HttpContext.Request.RawUrl
    };
    filterContext.Result = new RedirectResult (builder.ToString ());
   }
   else
   {
    throw new HttpException ((int)HttpStatusCode.Forbidden, "Access forbidden. The requested resource requires an SSL connection.");
   }
  }
 }

 public static bool Enable { get; set; }
}
Todd Smith
Thanks for the reply. I have the attributes attached at the controller level, not at the action level. BTW, I like your Enable enhancement.
Rich
How do you use Enable though? say in my dev environment I don't want it to be SSL?
Blankman
What does Validate.IsNotNull(...) do? I pasted the code, but don't have Validate (I don't want to install futures hehe)
Blankman
Validate is borrowed from https://kigg.svn.codeplex.com/svn/v2.x/Core/Helper/CheckArgument.cs
Todd Smith
For Enable I set it to true/false based on the web.config during application startup.
Todd Smith