【问题标题】:Must each API call have a unique AddAntiForgery token?每个 API 调用都必须具有唯一的 AddAntiForgery 令牌吗?
【发布时间】:2018-06-13 08:22:02
【问题描述】:

我知道在 FORM 中调用 Html.AddAntiForgeryToken 会起作用。 但是对于没有 Form 的情况,应该从哪里/如何获得防伪令牌?

每个令牌都必须是唯一的吗?或者网络应用可以在整个会话期间使用相同的防伪令牌吗?

【问题讨论】:

  • 你想用AntiForgeryToken解决什么问题?
  • 我想知道是否可以将相同的有效令牌用于用户会话中的所有 http 请求(只要会话仍然有效)。

标签: javascript asp.net asp.net-mvc antiforgerytoken


【解决方案1】:

AntiForgeryToken 值属于页面而不是form。如果您将多个表单(当然不是嵌套的!!!)与@Html.AntiForgeryToken() 放在同一页面上,那么所有值都将相同。当页面重新加载时(在GET 或POST 之后),值会发生变化。
在内部,Web 服务器设置 HttpOnly Cookie(在 AntiForgeryConfig 类中定义的名称)并将接收到的值与该 cookie 值进行比较。
如果您从该页面进行 API (AJAX) 调用会怎样?当然,您可以拨打任意数量的电话。
如果页面上没有form怎么办?您需要添加 fake form。像这样。

@{
    var attr = new Dictionary<string, object>();
    attr.Add("id", "anti-forgery"); //sic!
}
@using (Html.BeginForm("", "fake-form", FormMethod.Post, attr))
{
    @Html.AntiForgeryToken()
}

然后立即设置所有您的 AJAX 调用。

<script>
    'use strict';
    $(document).ready(function () {
        $.ajaxSetup({
            dataType: 'json',
            method: 'POST',
            contentType: 'application/json',
            headers: antiForgery({}) //put antiforgerytoken into ajax request header
        });
        function antiForgery(data) {
            data.__RequestVerificationToken = $('#anti-forgery input[name=__RequestVerificationToken]').val();
            return data;
        }

    });

</script>

在服务器端,您需要使用并验证请求。以下方法使用自定义属性类。

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class ValidateJsonAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationContext filterContext)
    {
        if (filterContext == null)
        {
            throw new ArgumentNullException("filterContext");
        }

        var httpContext = filterContext.HttpContext;
        var cookie = httpContext.Request.Cookies[AntiForgeryConfig.CookieName];
        AntiForgery.Validate(cookie != null ? cookie.Value : null, httpContext.Request.Headers["__RequestVerificationToken"]);
    }
}

现在你只用这个属性装饰你的控制器方法。

[HttpPost]
[ValidateJsonAntiForgeryToken] //this one
public async Task<JsonResult> ProcessRq(MyModel model)
{
    //do work
}

如果您创建纯 API (RESTfull) 服务,则有类似的方法。客户端应用首先必须请求和接收某种身份验证令牌,并将其添加到所有下一个请求中(在会话期间)。

【讨论】:

  • 我想最大的问题是:防伪令牌可以在表单之外生成吗?
  • 在这种情况下它被称为API Key
猜你喜欢
  • 2014-10-19
  • 2013-06-25
  • 1970-01-01
  • 2011-06-29
  • 1970-01-01
  • 1970-01-01
  • 2011-07-20
  • 2012-01-20
  • 1970-01-01
相关资源
最近更新 更多