MVC3 URL参数 - 避免恶意攻击/安全漏洞

时间:2012-04-11 16:30:36

标签: asp.net-mvc-3 security url parameters

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

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

如果在网址:http://myWebsite.com/User/Details/1234中传递了ID,则用户可以将其更改为 http://myWebsite.com/User/Details/4567并可能退出不同用户的详细信息。

将此值放在隐藏字段中,然后POSTing也不会很好,因为“view source”会显示该值。

非常感谢

1 个答案:

答案 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)
{
    ...
}