Monday, July 25, 2011

implement ssl custom attribute in MVC

Example of how to implement your SSL Custom Attribute in MVC

· If it is login, then we must force it into secure otherwise we need to force to unsecure.

· Ideally in LoginController, we can use this attribute [CustomRequireHttps] which will force to use SSL

· For other controller, we can use this attribute [CustomRequireHttps(false)] which will force not to use SSL

· For other controller which always not required SSL we can create other attribute to force not to use SSL [CustomNotRequireHttps]

/// Represents an attribute that forces an unsecured HTTP request to be re-sent over HTTPS.
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
public class CustomRequireHttpsAttribute : FilterAttribute, IAuthorizationFilter
{
private bool _ForceOnLoggedIn = false;

///
/// Constructor
///

///
public CustomRequireHttpsAttribute() : this(false);

///
/// Constructor
///

///
public CustomRequireHttpsAttribute(bool forceOnLoggedIn)
{
this._ForceOnLoggedIn = forceOnLoggedIn;
}



/// Handles unsecured HTTP requests that are sent to the action method.
/// An object that encapsulates information that is required in order to use the attribute.
/// The HTTP request contains an invalid transfer method override. All GET requests are considered invalid.
protected virtual void ForceSecure(AuthorizationContext filterContext)
{
if (!filterContext.HttpContext.Request.IsSecureConnection)
{
if (!string.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
{
//throw error if the request is not get
throw new InvalidOperationException("MyRequireHttpsAttribute_MustUseSsl");
}

string url = "https://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
filterContext.Result = new RedirectResult(url);
}
}

/// Force unsecure page only deal with get method
/// An object that encapsulates information that is required in order to use the attribute.
/// The HTTP request contains an invalid transfer method override. All GET requests are considered invalid.
protected virtual void ForceUnsecure(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Request.IsSecureConnection)
{
//if it is secure page
if (string.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
{
//only deal with get method
string url = "https://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
filterContext.Result = new RedirectResult(url);
}
}
}



/// Determines whether a request is secured (HTTPS) and, if it is not, calls the method.
/// An object that encapsulates information that is required in order to use the attribute.
/// The parameter is null.
public virtual void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}

if (_ForceOnLoggedIn == false)
{
this.ForceSecure(filterContext);
}
else
{
//check if Login
if (filterContext.RequestContext.HttpContext.User.Identity.IsAuthenticated)
{
//if login then need to force secure page
this.ForceSecure(filterContext);
}
else
{
//if not login then need to force to unsecure page
this.ForceUnsecure(filterContext);
}
}

}

No comments: