I am using the FormsA开发者_运维百科uthenticationService along with AccountMembershipService to handle membership and log in. I need a way to force a user to complete their profile when they log into the site, or go to a area that requires [Authorize()], before being able to continue on the site.
I was thinking about using a GlobalFilter on the AuthorizationContext but not sure if this would work as required.
Any ideas?
Following a bit of digging about I managed to find a way to achieve this.
First created a global filter
using System.Web.Mvc;
using Microsoft.Practices.Unity;
public sealed class LogOnAuthorize : AuthorizeAttribute
{
[Dependency]
public Service.IDaoService dao { get; set; }
public override void OnAuthorization(AuthorizationContext filterContext)
{
string SessionKey = "ProfileCompleted";
bool Authorization = filterContext.ActionDescriptor.IsDefined(typeof(AuthorizeAttribute), true)
|| filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AuthorizeAttribute), true);
bool ContainsIgnore = filterContext.ActionDescriptor.IsDefined(typeof(IgnoreCompleteProfileAttribute), true)
|| filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(IgnoreCompleteProfileAttribute), true);
if ((Authorization) && (!ContainsIgnore))
{
var ctx = System.Web.HttpContext.Current;
if (ctx != null)
{
if (filterContext.HttpContext.User.Identity.IsAuthenticated)
{
if (ctx.Session[SessionKey] == null)
{
Models.UserDetail user = dao.UserDao.GetByEmail(filterContext.HttpContext.User.Identity.Name);
if (user != null)
ctx.Session[SessionKey] = user.CompletedAccount;
}
bool ForceRedirect = ((ctx.Session[SessionKey] == null) || ((bool)ctx.Session[SessionKey] == false));
string ReturnUrl = string.Empty;
if ((filterContext.HttpContext.Request != null) && (!string.IsNullOrEmpty(filterContext.HttpContext.Request.RawUrl)))
ReturnUrl = filterContext.HttpContext.Request.RawUrl.ToString();
if (ForceRedirect)
filterContext.Result = new RedirectToRouteResult("CompleteAccount", new System.Web.Routing.RouteValueDictionary { {"ReturnUrl" , ReturnUrl} });
}
else
base.OnAuthorization(filterContext);
}
else
base.OnAuthorization(filterContext);
}
}
}
Then registed it up in the global.asax.cs
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new LogOnAuthorize());
}
For any actions that I needed to be authorised but not perform the check on I used
[Authorize()]
[IgnoreCompleteProfileAttribute()]
public ActionResult LogOff()
{
// Code Here
}
Which used this class
using System;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class IgnoreCompleteProfileAttribute : Attribute { }
Which all works well for what I needed, hope this helps someone.
I think you're on the right path with the global filter. You'd simply implement a check in the attribute that if the current user is authenticated and certain profile information is missing redirect them to the edit profile page. Depending on how you implement the redirect you could also inject some sort of feedback message to be displayed on the edit profile page explaining why they were redirected.
精彩评论