防止参数篡改和使用 Javascript 发送值的最佳方法?

Best way to prevent parameter tampering and send values with Javascript?

我正在向控制器发送一个表单并使其异步。我以隐藏的输入形式存储值。单击按钮时,将调用 javascript 函数。它既从输入字段中获取值,又从隐藏的输入表单中获取值。然后它向控制器发送一个 json 字符串来处理这个请求。

控制器:

[HttpPost, Authorize] 
public ActionResult DoSomeStuff (string leagueName, string doSomething)  {
    var service = new Service(_db);
    var league = service.GetLeague(leagueName);
    if (league != null) {
        // validate doSomething
        league.Action = doSomething;
        _db.SaveChanges();
    }

    return new EmptyResult(); 
}

Javascript:

$(document).on("click", "#submitForm", function () {
    var json = {
            "leagueName": $("input[name=leagueName]").val(),
            "doSomething": $("input[name=doSomething]").val()
    };

    $.post("/Home/DoSomeStuff/", json, function () {
        // async display something
    });
}

Html:

<input type="text" name="doSomething">
<button type="submit" id="submitForm"</button>
<input type="hidden" name="leagueName" value="@item.League.LeagueName" />

What is the best way to let javascript fetch a stored value (more secure way then input type hidden)?

How can I prevent some user from altering the value from the input type hidden field?

如果值需要来自客户端(并且是 HTTP 请求的一部分),那么您绝对无法阻止客户端修改其内容。如果客户端不应该修改某些字段的内容,那么这些字段与您的标记无关,并且是回发 HTTP 请求的一部分(无论是作为隐藏字段还是您想到的任何标记元素)。它们应该安全地驻留在您的服务器(数据库?)上,并使用来自客户端的一些标识符进行检索。显然,客户端是否可以访问与此标识符相关的信息取决于称为授权的东西。基本上,您应该首先知道您的客户是谁(身份验证),然后在您的数据模型中验证该客户是否有权访问相应的记录。就这么简单。

[HttpPost]
[Authorize] 
public ActionResult DoSomeStuff (string id, string doSomething)  
{
    var service = new Service(_db);
    var league = service.GetLeagueById(id);
    if (!HasAccessToLeague(User.Identity.Name, league)) 
    {
        // you are not suppose to modify the contents of this league
        // throw him a 404 or something
    }
    else
    {
        if (league != null) 
        {
            // validate doSomething
            league.Action = doSomething;
            _db.SaveChanges();
        }
    }

    return new EmptyResult(); 
}

显然,HasAccessToLeague(string username, string leagueId) 方法的实施将在很大程度上取决于您的数据模型以及您的授权逻辑。

您还在问题标题中使用了 XSS,但这里您的问题与 XSS 或 javascript 无关,而是在您的 Web 应用程序中设计授权层。

How can I prevent some user from altering the value from the input type hidden field?

你不能!

What is the best way to let javascript fetch a stored value (more secure way then input type hidden)?

一般规则是,不要相信来自客户端的数据。在做任何事情之前,你应该总是在服务器上验证它。

如果您担心用户将表单中的联盟名称字段值更新为其他用户的联盟名称和post,您应该做的是明确检查用户是否具有适当的权限在您的服务器代码中对 posted 联盟做一些事情。

[HttpPost, Authorize] 
public ActionResult DoSomeStuff (string leagueName, string doSomething)  {
    var service = new Service(_db);
    var league = service.GetLeague(leagueName);

    // Now check whether the current user has access/permission 
    // to perform some operation on this league.
    // Ex : if(!service.IsUserAuthorizedToDoSomething(league))
    //     {
    //      return View("NotAuthorized");
    //     }
    //to do: Return something
}

当然可以!毕竟,您的服务器应用程序设法跟踪当前登录的用户正在使用不安全的客户端存储。

当用户登录时,服务器将生成一条秘密消息并将其存储在传递给客户端的加密令牌中,并保存在 cookie 中(这只是另一种不安全的客户端数据存储)。当你向服务器发送请求时,它会获取 cookie,对其进行解密,并检查其中的数据以判断用户是谁。

您也可以这样做 - 对于隐藏字段,对其进行加密,将它们放入隐藏输入(或 cookie,如果您愿意),然后将它们发送回服务器。但是,如果您也发送纯文本,则只能在客户端 javascript 中使用它们,这意味着您仍然需要在服务器上执行一些检查,但是检查可以像将加密值与隐藏的表单值,如果不匹配,则拒绝请求。

不过要记住的事情是,encrypion 很慢。从数据库中获取值可能会更快,尽管您可能会为这些值使用缓存。 YMMV.

另一种选择是生成一个包含值的 javascript 文件,并确保客户端浏览器无法使用内容安全策略等安全功能编辑它们。缺点是无法在 html 中使用这些值(显然用户可以在那里编辑它们)因此您必须通过 js 调用将数据传回服务器。