0

导航到新网页时,是否有传递 ID 的“最佳实践”。

例如,一个人注册使用一个网站,他们得到一个 ID,这需要在用于从数据库中检索相关数据的网站/页面的其余部分传递。

如果 Id 在 url 中传递: http://myWebsite.com/User/Details/1234,用户可以将其更改为 http://myWebsite.com/User/Details/4567并可能收回其他用户的详细信息。

将此值放在隐藏字段中然后发布也不会很好,因为“查看源代码”会显示该值。

非常感谢

4

1 回答 1

4

这就是为什么您应该始终验证此 id 属于当前经过身份验证的用户的原因。当前已通过身份验证的用户存储在表单身份验证 cookie 中,并且用户无法更改,因为该值已加密。此 cookie 在用户登录时发出,您可以在任何有实例的地方访问它HttpContextBase(这几乎是 MVC 模式的 V 和 C 部分的任何地方)。

例如,像这样:

[Authorize]
public ActionResult Foo(int id)
{
    string currentUser = httpContext.User.Identity.Name;
    // TODO: go ahead and check in your backed that the id 
    // belongs to the currently connected user
    ...
}

显然,在所有控制器操作中一遍又一遍地编写这些检查很快就会变得无聊,更不用说这种方法的干燥性了。这就是为什么建议编写一个自定义的 Authorize 属性,该属性将在进入控制器操作之前执行这些检查。然后,您将使用此自定义属性装饰您的控制器操作,并且您将确定如果代码已到达操作内部,则意味着当前用户是作为参数传递的 id 的所有者。这个 id 作为参数传递的方式并不重要。可以是路由数据、查询字符串、POST 等等。用户可以随意修改它。重要的部分是您确保他输入的值与您的域授权逻辑一致。

所以:

public class AuthorizeOwnerAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var authorized = base.AuthorizeCore(httpContext);
        if (!authorized)
        {
            // the user is either not authenticated or not authorized
            // no need to continue any further
            return false;
        }

        // at this stage we know that the user is authenticated and
        // authorized (in roles), so let's go ahead and see who this 
        // user is
        string username = httpContext.User.Identity.Name;

        // now let's read the id. In this example I fetch it from
        // the route data but you could adapt according to your needs
        string id = httpContext.Request.RequestContext.RouteData.Values["id"] as string;

        // Now that we know the user and the id let's go ahead and 
        // check in our backend if the user is really the owner
        // of this id:
        return IsOwner(username, id);
    }

    private bool IsOwner(string username, string id)
    {
        // go ahead and hit the backend             
        throw new NotImplementedException();
    }
}

进而:

[AuthorizeOwner]
public ActionResult Foo(int id)
{
    ...
}
于 2012-04-11T16:32:06.293 回答