导航到新网页时,是否有传递 ID 的“最佳实践”。
例如,一个人注册使用一个网站,他们得到一个 ID,这需要在用于从数据库中检索相关数据的网站/页面的其余部分传递。
如果 Id 在 url 中传递: http://myWebsite.com/User/Details/1234,用户可以将其更改为 http://myWebsite.com/User/Details/4567并可能收回其他用户的详细信息。
将此值放在隐藏字段中然后发布也不会很好,因为“查看源代码”会显示该值。
非常感谢
导航到新网页时,是否有传递 ID 的“最佳实践”。
例如,一个人注册使用一个网站,他们得到一个 ID,这需要在用于从数据库中检索相关数据的网站/页面的其余部分传递。
如果 Id 在 url 中传递: http://myWebsite.com/User/Details/1234,用户可以将其更改为 http://myWebsite.com/User/Details/4567并可能收回其他用户的详细信息。
将此值放在隐藏字段中然后发布也不会很好,因为“查看源代码”会显示该值。
非常感谢
这就是为什么您应该始终验证此 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)
{
...
}