简体   繁体   English

ASP.NET MVC-授权重构

[英]ASP.NET MVC - Authorization Refactor

The problem i see with this code, is that it's going to be reused a lot; 我在这段代码中看到的问题是,它将被大量重用。 anything being edited/created by a authenticated user (except for Site administrators) will only have access to a their "studios" objects. 经过身份验证的用户(网站管理员除外)正在编辑/创建的任何内容都只能访问其“工作室”对象。

My question to you all; 我对大家的问题; how would you re-factor this so the service layer can be abstracted away from the knowledge of the client. 您将如何重构它,以便可以从客户的知识中抽象出服务层。 I intend to reuse the service layer in a stand-alone desktop application later. 我打算稍后在独立的桌面应用程序中重用服务层。

Please shed some light on my erroneous ways! 请阐明我的错误方法! I greatly appreciate it. 我非常感谢。

AuthorizeOwnerAttribute.cs (AuthorizeAttribute) AuthorizeOwnerAttribute.cs (AuthorizeAttribute)

protected override bool AuthorizeCore(HttpContextBase httpContext)
{
    // Get the authentication cookie
    string cookieName = FormsAuthentication.FormsCookieName;
    HttpCookie authCookie = httpContext.Request.Cookies[cookieName];

    // If the cookie can't be found, don't issue the ticket
    if (authCookie == null) return false;

    // Get the authentication ticket and rebuild the principal & identity
    FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
    string[] userData = authTicket.UserData.Split(new[] { '|' });

    int userId = Int32.Parse(userData[0]);
    int studioID = Int32.Parse(userData[1]);
    GenericIdentity userIdentity = new GenericIdentity(authTicket.Name);
    WebPrincipal userPrincipal = new WebPrincipal(userIdentity, userId, studioID);
    httpContext.User = userPrincipal;

    return true;
}

Inside of my "User" Controller attach this attribute to any method that requires an owner 在我的“用户”控制器内部,将此属性附加到需要所有者的任何方法上

    [AuthorizeOwner]
    public ActionResult Edit(int Id)
    {
        IUser user = userService.GetById(HttpContext.User, Id);
        return View(user);
    }

Now, in my Service layer is where I'm checking the passed down IPrincipal if it has access to the object being requested. 现在,在我的服务层中,我正在检查传递的IPrincipal是否有权访问所请求的对象。 This is where it's getting smelly: 这是它越来越臭的地方:

UserService.cs UserService.cs

    public IUser GetById(IPrincipal authUser, int id)
    {
        if (authUser == null) throw new ArgumentException("user");

        WebPrincipal webPrincipal = authUser as WebPrincipal;
        if (webPrincipal == null) throw new AuthenticationException("User is not logged in");

        IUser user = repository.GetByID(id).FirstOrDefault();
        if (user != null)
        {
            if (user.StudioID != webPrincipal.StudioID) throw new AuthenticationException("User does not have ownership of this object");
            return user;
        }

        throw new ArgumentException("Couldn't find a user by the id specified", "id");
    }

I'm not sure I'd be storing the actual IDs in the cookie, that's a little too exposed. 我不确定我是否会将实际ID存储在cookie中,这有点暴露了。 I'd be more inclined to use the Session hash to store that data thus keeping it on the server and not exposed. 我更倾向于使用Session哈希存储该数据,从而将其保留在服务器上而不公开。

I'd also use the Model (by passing the userID) to determine which objects to return, ie those that have a matching studioID. 我还将使用模型(通过传递用户ID)来确定要返回的对象,即具有匹配studioID的对象。 That way your controller would only ever have to call "GetObjects(int id)", if they don't have access to anything then you get a null or empty collection back. 这样,您的控制器将只需要调用“ GetObjects(int id)”,如果它们无权访问任何内容,那么您将获得一个null或空集合。 That feels cleaner to me. 这对我来说比较干净。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM