【问题标题】:ASP.NET, MVC4, authorization: users should see only own contentASP.NET、MVC4、授权:用户应该只看到自己的内容
【发布时间】:2014-01-27 19:30:13
【问题描述】:

现在我的网站结构如下:

前端:网站\user1、网站\user2

后端:website\account\user1,website\account\user2

网站\帐户控制器应用了通用 [Authorize] 属性。这还不够,因为任何授权用户都可以通过访问 website\account\ url(如果他知道他的名字)来访问其他用户支持的功能。

解决此问题的最佳方法是什么?

到目前为止,我有两种方法:

  1. 创建自定义 Authorize 属性,检查控制器上下文,从中提取用户信息并将其与 ASP.NET 中的当前授权用户进行比较:

     var currerntUserId = (long)System.Web.Security.Membership.GetUser().ProviderUserKey;
     return ExtractCurrentUserId(filterContext) == currerntUserId;
    
  2. 从后端 URL 中删除部分并让所有用户访问 \account。当前用户信息将由 ASP.NET 框架提供。

【问题讨论】:

  • 为什么后端没有website\my-account,只根据当前Controller.User.Identity.Name查询数据库?

标签: c# asp.net asp.net-mvc asp.net-mvc-4 authorization


【解决方案1】:

这个怎么样?

路由/网站/我的帐户

[Authorize]
public class MyAccountController : Controller
{
    public ActionResult Index()
    {
        var userData = System.Web.Security.Membership.GetUser();
        // note you could also get this from db using this.User.Identity.Name
        return View(userData);
    }
}

通过这种方式控制授权要容易得多,因为我们没有通过路由参数将用户 ID 传递给操作方法。某人可以访问特定用户帐户的后端的唯一方法是作为该用户登录。

回复cmets:

为了回答您在 cmets 中关于更容易/更难/更好/我的偏好是什么的问题,我将继续做我的最终答案“视情况而定”。

这取决于数据的敏感性、管理员可以做哪些用户不允许做的事情(反之亦然)、需要保护多少控制器操作、公共/帐户/管理员的视图有多相似对数据的看法等。您的问题中陈述的几乎所有内容以及此处的所有答案都是有效的方法。您当然可以使用 ActionFilter 并保留用户 URL,或者您可以直接在操作方法中执行此操作(如果没有很多),更改您的 URL 架构,实现模拟(或不实现)等。

【讨论】:

  • 在花了这么多时间试图保护用户名特定的 url 之后,我倾向于这种方法,让 ASP.NET 为我处理授权。
  • 所以您需要一个用户名特定的 URL 用于自我管理页面?这样管理员是否也可以编辑用户数据,即使他们没有以用户身份登录?
  • 我真的不需要特定于用户名的 URL。我只是想为管理员轻松访问用户数据会很好(就像你已经说过的那样)。拥有通用后端 url + ASP.NET 成员资格会更容易/更好,我将不得不为管理员创建自定义后端,他们可以在其中查看/编辑用户数据----或----用户特定的 URL使用自定义授权码,但管理员可以轻松访问?
  • 授予管理员访问权限的另一个选项是强制他们以他们想要编辑的用户身份登录——也就是模拟。为此,您可以为管理员提供一个页面,让他们选择用户,将该用户的 auth cookie 写入浏览器,然后重定向到用户的帐户页面。问题是如果有多个用户要编辑,会有很多上下文切换(模拟/恢复到管理员帐户)。
  • 模仿很有趣。我会看看。那么,您会亲自走这条路,而不是搞乱自定义授权吗?自定义授权让我担心安全问题。
【解决方案2】:

当您从数据存储区(很可能是数据库)中检索用户数据时,您应该只检索经过身份验证的用户的用户名的数据。在您的控制器中,这将为您提供当前经过身份验证的用户的用户名:

User.Identity.Name

所以你可以这样做:

return ExtractCurrentUserId(filterContext) == User.Identity.Name;

【讨论】:

  • MembershipUser.ProviderUserKeyUser.Identity.Name 一样吗?看起来 OP 是 long,但 IIdentity.Namestring
  • 没有。一个将为用户返回(通常)GUID。另一个将返回用户名。我已经看到 User.Identity.Name 是授权的首选。
  • 我使用自定义会员提供者,所以 Identity.Name 和 ProviderUserKey 无论如何都来自同一个实体。
【解决方案3】:

如果您将基于角色的身份验证与 SimpleMembership 一起使用,您可以执行以下操作并为用户提供应该能够访问某些控制器操作的角色:

public class MyAccountController : Controller
{
    [Authorize(Roles = "Admin")]
    public ActionResult User1()
    {
       // do user1 work
    }

    [Authorize]
    public ActionResult User2()
    {
       // do user2 work
    }
}

【讨论】:

    猜你喜欢
    • 2021-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多