导航到新网页时,是否有传递ID的“最佳实践”。
例如,一个人注册使用一个网站,他们会得到一个Id,这需要传递到其余的网站/页面,用于从数据库中检索相关数据。
如果在网址:http://myWebsite.com/User/Details/1234中传递了ID,则用户可以将其更改为 http://myWebsite.com/User/Details/4567并可能退出不同用户的详细信息。
将此值放在隐藏字段中,然后POSTing也不会很好,因为“view source”会显示该值。
非常感谢
答案 0 :(得分: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)
{
...
}