Simple Authorization in MVC3 with Forms Authentication

对着背影说爱祢 提交于 2020-01-02 06:29:13

问题


I'm trying to do what should be a simple thing in MVC3.

I've got an application that uses forms authentication to authenticate users with a 3rd party SSO. The SSO, on successful login, posts back to a specific controller action on my application. I then call FormsAuthentication.SetAuthCookie(user,false);.

I'm trying to implement some level of authorization. Simply, a user can exist in a number of different roles, e.g. Admin and Developer. Some controller actions should only be available to certain roles. Details of which roles a user belongs to is obtained by making a call to another external API, which returns a simple JSON response indicating.

In theory, this should be as simple as doing something like this after I set the FormsAuthentication cookie:

string[] rolelist = GetRoleListForUserFromAPI(User.Identity.Name);
HttpContext.User = new GenericPrincipal(User.Identity, rolelist);

However, I can't call this directly after calling SetAuthCookie, because HttpContext.User isn't anything meaningful at this point.

I could try setting this on every request, but ever request to my app would mean a roundtrip API call.

The most promising approach I've seen so far is to create a custom Authorization attribute and override OnAuthorization to do something like this:

public override void OnAuthorization(AuthorizationContext filterContext)
{
    if (<some way of checking if roles have already been set for this user, or role cache has timed out>)
    {
        string[] rolelist = GetRoleListForUserFromAPI(filterContext.HttpContext.User.Identity.Name);
        filterContext.HttpContext.User = new GenericPrincipal(filterContext.HttpContext.User.Identity,rolelist);
    }
}

I could then use [MyCustomAuthorization(Roles="Admin")] in front of controller actions to make the magic happen.

However, I've no idea how to detect whether or not the current HttpContext.User object has had its roles set, or whether it was set over a certain time ago and another API trip is needed.

What's the best approach for this?


回答1:


My first thought is that you should investigate implementing a custom role provider. This might be overkill but seems to fit in with the role-based plumbing.

More info from MSDN here.




回答2:


Another way would be to store the roles in the UserData property of the FormsAuthentcationTicket. This could be done with comma delimited string.

http://msdn.microsoft.com/en-us/library/system.web.security.formsauthenticationticket.formsauthenticationticket

Then on AuthenticateRequest method, you could pull the ticket back, grab the roles data and assign it to the current user using a generic principal.




回答3:


You should override PostAuthenticateRequest

protected void Application_OnPostAuthenticateRequest(object sender, EventArgs e) 
{
    if (HttpContext.Current.User.Identity.IsAuthenticated)
    {
        string[] rolelist = GetRoleListForUserFromAPI(User.Identity.Name);
        HttpContext.User = new GenericPrincipal(User.Identity, rolelist);
    }
}

It's invoked after forms authentication is finished with it's processing.

http://msdn.microsoft.com/en-us/library/ff647070.aspx

Update

I had the wrong method signature (just checked in one of my own applications).




回答4:


Much to the aghast of some, the session object ISNT a bad idea here. If you use temp data, you already take a hit for the session.

Storing this data in the cookie, well - Forms auth tokens have already been exploited in the POET vulnerability from a year and a half ago, so in that case someone could've simply formed their own cookie with the "admin" string in it using that vulnerability.

You can do this in post authenticate as @jgauffin mentioned. If the session state isn't available there you can use it then in Application_PreRequestHandlerExecute and check it there.

If you want to check if session state is available in either see my code at: How can I handle forms authentication timeout exceptions in ASP.NET?

Also whenever using forms auth and sessions, you always want to make sure the timeouts are in sync with each other (again the above code)



来源:https://stackoverflow.com/questions/10949070/simple-authorization-in-mvc3-with-forms-authentication

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!