I am implementing the security part of an ASP MVC application and I am getting confused in how to implement a custom membership provider since there seems to be a lot of functionallity that I wouldn't use.
The application I'm porting usually managed the security through an object stored in session called "SecurityManager" which cont开发者_StackOverflow中文版ained the current user and a form permission collection. Each item of this collection contains the permission per form of the logged user and permissions per field of that form (in case they were needed if not full control of the form is assumed).
However, when I see the methods of the MembershipProvider and the AuthorizeAttribute tag they assume that I will use roles which my application does not use, we just have permission groups which are just the permissions grouped together for certain user groups, but they tend to change in time.
So basically the only thing I would need would be something that when a request is made would check if the security manager is stored in session (if it is not the user is not authenticated and will be redirected to the login page) and then get that object from session and perform operation with it to know if the user can or cannot access the view.
What would be the best approach for this? I've read that bypassing the custom membership was not a good idea.
Update: I recently came up against this and figured out how to use the AuthorizeAttribute
to do exactly as you wanted. My attribute, that verifies if the user is an administrator, works as follows:
public class AuthorizeAdminAttribute : AuthorizeAttribute
{
public bool IsValidUser { get; protected set; }
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext == null) { throw new ArgumentNullException("httpContext"); }
// Make sure Forms authentication shows the user as authenticated
if (httpContext.User.Identity.IsAuthenticated == false) return false;
// Retrieve the unit of work from Windsor, and determine if the current user is an admin
var unitOfWork = Bootstrapper.WindsorContainer.Resolve<IUnitOfWork>();
var user = new UserByIdQuery(unitOfWork).WithUserId((int)Membership.GetUser().ProviderUserKey).Execute();
if (user == null)
return false;
// Otherwise the logged in user is a real user in the system
IsValidUser = true;
return user.IsAdmin;
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (filterContext == null) { throw new ArgumentNullException("filterContext"); }
// If this user is a valid user but not an admin, redirect to the homepage
if (IsValidUser)
{
// Redirect them to the homepage
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary
{
{ "area", "" },
{ "action", "Index" },
{ "controller", "Home" }
});
}
else
{
// User isn't logged in, perform normal operations
base.HandleUnauthorizedRequest(filterContext);
}
}
}
Essentially you have to user the AuthorizeCore()
to determine if the user is logged in, store that result, and then perform authorization for the roles in your system. Then in your HandleUnauthorizedRequest
you have to figure out if the request was unauthorized because the user wasn't logged in, or if it was because they weren't authorized.
Old Answer I accomplish using the
Authorize
attribute by creating a subclass of the AuthorizeAttribute
class. So for example:
public class MyCustomAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext == null) { throw new ArgumentNullException("httpContext"); }
// Make sure Forms authentication shows the user as authenticated
if (httpContext.User.Identity.IsAuthenticated == false) return false;
// replace with whatever code you need to call to determine if the user is authorized
return IsUserAuthorized();
}
}
Now when a controller or action is called, and is decorated with [MyCustomAuthorize]
it will run this code to determine if the user is authorized based on your custom logic, and if not will redirect them exactly how the [Authorize]
attribute would.
I don't know if this is the best approach, but it is what I came up with.
精彩评论