How to implement authorization checks in ASP.NET M

2019-01-17 13:12发布

问题:

This will be my first ASP.NET MVC application with forms authentication so I am trying to make sure I don't miss anything. The scenario is this: Public / Secured Areas.

Within the private area it is even further limited to specific areas / user. These 'Areas' are defined by customizations to the base area that is customized per user group.

So for example a user could get to url /Area/Controller/Action. They would need to have permission to the secured area or they would be redirected to the sign-in view.

I have been reading about the AuthorizeAttribute but I am not sure how/where I should be doing these basic checks. My initial hunch would be to store a user object in the session after a successful sign-in with the user's IP and details about what they have access to etc.

The authorization check for each secured controller call would verify that a valid user object exists in the session, the IPs still match up, and the user has access to the specific area. Is there any obvious holes to this setup?

Edit: Where/how do I implement these checks so that when a controller is tagged with [Authorize] it will perform those session object checks?

Any pointers or suggestions would be much appreciated. Thanks.

回答1:

Well it looks like I went with a custom AuthorizeAttribute. It was actually very simple. Here is the code:

namespace MyApp.Custom.Security
{
    public class Secure : AuthorizeAttribute
    {
        /// <summary>
        /// Checks to see if the user is authenticated and has a valid session object
        /// </summary>        
        /// <param name="httpContext"></param>
        /// <returns></returns>
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (httpContext == null) throw new ArgumentNullException("httpContext");

            // Make sure the user is authenticated.
            if (httpContext.User.Identity.IsAuthenticated == false) return false;

            // This will check my session variable and a few other things.
            return Helpers.SecurityHelper.IsSignedIn();
        }
    }
}

Then on my controllers I just have to put a [Secure] attribute and it uses my function above anytime that controller is accessed. Pretty simple. I also made a [SecureByRole] attribute as well that does all the same stuff but checks for my custom role information as well. No need to for all that built in voodoo from the canned Membership :)



回答2:

Try to look at the RoleProvider class. This is the basic framework of how ASP.net use rolebased authorization to users. And I think you should use [Authorize(Roles='...')] attribute to make use of that.



回答3:

In my previous application I used a simple HttpModule to augment the authenticated user with additional roles etc ( I did this because my requirements were very constrained ).

public class AuthorisationModule : IHttpModule
{
    public void Init( HttpApplication context )
    {
        context.AuthorizeRequest += AuthorizeRequest;
    }

    private void AuthorizeRequest(object sender, EventArgs e)
    {
        var currentUser = HttpContext.Current.User;
        if( !currentUser.IsAuthenticated() )
        {
            return;
        }

        var roles = new List<string>();
        // Add roles here using whatever logic is required

        var principal = new GenericPrincipal( currentUser.Identity, roles.ToArray() );
        HttpContext.Current.User = principal;
    }

    public void Dispose()
    {
        if(HttpContext.Current == null )
        {
            return;
        }

        if(HttpContext.Current.ApplicationInstance == null)
        {
            return;
        }

        HttpContext.Current.ApplicationInstance.AuthorizeRequest -= AuthorizeRequest;
    }
}


回答4:

[Authorize]
public class BaseController : Controller
{
    protected override void OnAuthorization(AuthorizationContext authContext)
    {
        if
            (
            !User.Identity.IsAuthenticated &&
            Request.LogonUserIdentity != null &&
            Request.LogonUserIdentity.IsAuthenticated
            )
        {
            var logonUserIdentity = Request.LogonUserIdentity.Name;
            if (!string.IsNullOrEmpty(logonUserIdentity))
            {
                if (logonUserIdentity.Contains("\\"))
                    logonUserIdentity = logonUserIdentity.Substring(logonUserIdentity.IndexOf("\\") + 1);

                var db = new UsersContext();
                var loginUser =
                    db.UserProfiles.FirstOrDefault(x => x.UserName == logonUserIdentity);

                //Auto-Login Windows Identity
                if (loginUser == null)
                    loginUser = CreateUser(db, logonUserIdentity);

                if (loginUser != null)
                {
                    FormsAuthentication.SetAuthCookie(loginUser.UserName, true);

                    string returnUrl = Request.RawUrl;
                    if (!string.IsNullOrEmpty(returnUrl))
                        Response.Redirect(returnUrl);
                    Response.Redirect("~/");

                }
            }
        }
    }

    private static UserProfile CreateUser(UsersContext db, string logonUserIdentity)
    {
        var user = new UserProfile {UserName = logonUserIdentity};
        db.UserProfiles.Add(user);
        db.SaveChanges();
        return user;
    }
}