【问题标题】:How-to prevent CSRF / XSRF in ASP.NET Core MVC App Web API Controller如何在 ASP.NET Core MVC App Web API 控制器中防止 CSRF / XSRF
【发布时间】:2017-07-02 19:23:23
【问题描述】:

通过将 ValidateAntiForgeryToken 属性应用到操作并在表单中使用 sp-antiforgery=true,可以轻松地向 Asp.Net Core MVC 应用程序添加防伪功能。

如何保护 Web API 控制器的 CRUD 操作,该控制器使用具有 Authorize 属性的个人身份验证和客户端的 Kendo MVC Grid?

【问题讨论】:

  • 嗨,肖恩,感谢您的宝贵回答。我赞成并设置为已回答。今天我只找到了 2013 年的链接 dotnetcurry.com/aspnet/890/…,并想确保它仍然适用于 jQuery 的 Asp.Net Core 和 Kendo UI。再次感谢!
  • 任何时候,先生。我已经给出了该链接以及基于剑道的具体实现的参考

标签: c# kendo-grid asp.net-core-mvc kendo-asp.net-mvc kendo-ui-mvc


【解决方案1】:

您可以创建一个控制器并注入 IAntiforgery 以获取 XsrfToken,然后将其与验证请求一起发送。

[Route("api/[controller]")]
public class XsrfTokenController : Controller
{
    private readonly IAntiforgery _antiforgery;

    public XsrfTokenController(IAntiforgery antiforgery)
    {
        _antiforgery = antiforgery;
    }

    [HttpGet]
    public IActionResult Get()
    {
        var tokens = _antiforgery.GetAndStoreTokens(HttpContext);

        return new ObjectResult(new {
            token = tokens.RequestToken,
            tokenName = tokens.HeaderName
        });
    }
}

您可以在here上阅读更多相关信息

【讨论】:

  • 如何将它添加到客户端的 jQuery Grid 的 Kendo UI 中?谢谢。
  • @Ahmar:成功登录后如何刷新令牌?
【解决方案2】:

只有在客户端共享 cookie 时才会发生 CSRF 攻击。 我的意思是客户端可以访问来自多个 域(例如为您存储的每个站点的 cookie 的 Web 浏览器 访问)。但是,Web 应用程序 API 客户端通常只联系 单个域(您的 API 的域)。任何跨站攻击都不能使用 您的 API 中的 cookie 作为客户端不共享(HTTP 客户端在 Web 应用程序独立于移动浏览器中的 HTTP 客户端 - 或应该是)。因此,您的 Web 应用程序 API 应该已经是 如果 API 仅适用于您的移动应用程序,则对 CSRF 是安全的。

这里有一个通用指南,用于在此处讨论的 webapi 中实现防伪令牌。

Preventing CSRF Hacks in ASP.NET WebAPI

但由于您使用的是剑道网格,我们必须研究专门用于剑道网格的东西。

1:使用WEBAPI端点:

你可以喜欢使用数据: 通过读取传输的数据功能以常规方式发送防伪令牌

transport: {
    read: {
        url: url,
        type: "POST",
        data: {
            __RequestVerificationToken: $("input[name=__RequestVerificationToken]").val()
        }
    }

或者使用参数映射:

   @Html.AntiForgeryToken()

 <div id="grid"></div>
<script>
    $(document).ready(function () {
        $("#grid").kendoGrid({
            dataSource: {
                type: "json",
                transport: {
                    read: {
                        url: "/Home/GetProducts",
                        type: "POST"
                    },
                    update: {
                        url: "/Home/UpdateProduct",
                        type: "POST"
                    },
                    parameterMap: function (options, operation) {
                        options.__RequestVerificationToken = $("input[name=__RequestVerificationToken]").val();
                        return options;
                    }
                },
                schema: {
                    model: {
                        id: "ID",
                        fields: {
                            ID: { type: "number", editable: false },
                            Name: { type: "string" }
                        }
                    }
                },
                pageSize: 10
            },
            height: 250,
            filterable: true,
            sortable: true,
            pageable: true,
            editable: "inline",
            columns: ["ID", "Name", {command: "edit"}]
        });
    });
</script>

你的 webapi 控制器

        [ValidateAntiForgeryToken]
        public ActionResult GetProducts()
        {
            return Json(products);
        }

        [ValidateAntiForgeryToken]
        public void UpdateProduct(Product updatedProduct)
        {
            var product = products.FirstOrDefault(p => p.ID == updatedProduct.ID);
            UpdateModel(product);
        }

2:使用基于 Ajax 的调用

我们会让你在 Datasource 中使用 Data 函数来向 CRUD ops 发送防伪令牌

您需要在页面上添加它以生成令牌

@Html.AntiForgeryToken()

然后在剑道网格数据源配置中这样做

.DataSource(dataSource => dataSource
                .Ajax()
                .Model(model=>model.Id(m=>m.PersonID))
                    .Read(read => read.Action("GetPersons","Home").Data("sendAntiForgery"))
                    .Update(up => up.Action("UpdatePerson", "Home").Data("sendAntiForgery"))
            )

这是将令牌发送到 CRUD 操作的 javascript 方法

<script type="text/javascript">
    function sendAntiForgery() {
        return { "__RequestVerificationToken": $('input[name=__RequestVerificationToken]').val() }
    }
</script>

服务器端的控制器

        [ValidateAntiForgeryToken]
        public ActionResult GetPersons([DataSourceRequest] DataSourceRequest dsRequest)
        {
            var result = persons.ToDataSourceResult(dsRequest);
            return Json(result);
        }

        [ValidateAntiForgeryToken]
        public ActionResult UpdatePerson([DataSourceRequest] DataSourceRequest dsRequest, Person person)
        {
            if (person != null && ModelState.IsValid)
            {
                var toUpdate = persons.FirstOrDefault(p => p.PersonID == person.PersonID);
                TryUpdateModel(toUpdate);
            }


            return Json(ModelState.ToDataSourceResult());
        }

如需更多帮助,请查看剑道文档中的这些链接

http://www.telerik.com/forums/kendo-grid-antiforgerytoken#fPGvzDjUyEahRPNaTEo_TA http://www.telerik.com/forums/anti-forgery-tokens#VA3XA6lbT0WgeOwOQ3w_nQ

【讨论】:

  • 我在 /api/Read 端点上使用方法 1.) 收到 400(错误请求)。我可以给你发电子邮件吗?
猜你喜欢
  • 2017-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-15
  • 2018-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多