AJAX POST到Web API控制器和CSRF

10 浏览
0 Comments

AJAX POST到Web API控制器和CSRF

我基本上需要在我的Web API Controller中防止跨站请求伪造,这是MVC应用程序的一部分。我对任何想法都持开放态度。目前,我有一个MVC视图,使用ArcGIS for JavaScript API显示Esri地图。用户在地图上创建了一条路线,这条路线和它所穿越的各种要素可以通过AJAX POST保存。视图没有表单。这是因为我POST到服务器的所有数据都保存在内存中,不可见于屏幕上(或隐藏字段中)。\n所以,在我的MVC视图中,我有以下内容来获取防伪令牌:\n@functions{\npublic string GetTokenHeaderValue()\n{\n string cookieToken, formToken;\n AntiForgery.GetTokens(null, out cookieToken, out formToken);\n return cookieToken + \":\" + formToken;\n}\n}\n我在视图中有一个隐藏的输入框,但是意识到这是不好的,因为它同时具有与AntiForgery.Validation一起使用的“表单令牌”和cookie令牌:\n\n然后,在一个独立的JavaScript文件中(不是在视图中的脚本标签中),我对我的Web API Controller进行了Http POST。这是我将令牌添加到请求头的地方:\nvar headers = {};\nheaders[\'RequestVerificationToken\'] = $(\"#antiforgeryToken\").val();\n// Ajax POST to Web API Controller\n$.ajax({\n async: true,\n url: \'/api/RouteData\',\n type: \'POST\',\n headers: headers,\n data: requestData,\n dataType: \'json\',\n error: function (xhr, statusText, errorThrown) {\n console.log(\'Error saving route data! \' + errorThrown);\n },\n success: function (result) {\n }\n});\n注意:在请求体中进行POST的数据都保存在一个自定义的Dojo小部件中的内存中(因为页面使用ArcGIS for JavaScript显示Esri地图)。页面上没有表单,因为用户不输入数据。\n在服务器端的Web API Controller中将所有内容绑定在一起:\n[System.Web.Http.HttpPost]\n[ResponseType(typeof(RouteData))]\npublic async Task PostRouteData(RouteDataViewModel routeDataVM)\n{\n try\n {\n HttpRequestMessage httpRequestMessage = HttpContext.Current.Items[\"MS_HttpRequestMessage\"] as HttpRequestMessage;\n ValidateRequestHeader(httpRequestMessage);\n }\n catch (Exception ex)\n {\n _logger.Log(LogLevel.Error, ex, ex.Message);\n throw;\n }\n // 现在我们知道用户是他们自己说的那个人,执行更新操作\n}\nvoid ValidateRequestHeader(HttpRequestMessage request)\n{\n string cookieToken = \"\";\n string formToken = \"\";\n IEnumerable tokenHeaders;\n if (request.Headers.TryGetValues(\"RequestVerificationToken\", out tokenHeaders))\n {\n string[] tokens = tokenHeaders.First().Split(\':\');\n if (tokens.Length == 2)\n {\n cookieToken = tokens[0].Trim();\n formToken = tokens[1].Trim();\n }\n }\n AntiForgery.Validate(cookieToken, formToken);\n}\nAntiForgery.Validate是用于验证令牌的方法。\n我看到了这个【SO post】,给了我一些想法,但对我来说并没有完全解决问题。这个【post on ASP.net】也非常值得赞赏。\n对我来说不同的是(我想),我的JavaScript位于一个单独的文件中,无法调用服务器端的Razor函数来获取防伪令牌,对吗?有什么办法在没有表单的情况下防止CSRF?

0
0 Comments

问题的出现的原因:为了解决跨站请求伪造(CSRF)攻击,开发者使用了隐藏的输入字段来存储令牌,但有人质疑这样的解决方案是否安全。

解决方法:经过讨论后,人们认为已经实施的解决方案是可以接受的。尽管令牌都存在隐藏的输入字段中,但是由于CSRF的本质是防止其他网站代表用户进行POST请求,所以这个解决方案是有效的。如果用户在自己的站点上进行身份验证,并浏览到另一个试图代表用户进行POST请求的站点,该站点将无法获取到必要的令牌。

0
0 Comments

原因:CSRF(跨站请求伪造)是一种攻击方式,攻击者通过欺骗用户在受信任的网站上执行非用户意愿的操作。如果Web API没有进行CSRF保护,攻击者可以通过在其他网站上发布一个带有恶意代码的表单来执行一些恶意操作,比如删除账户。

解决方法:可以通过使用防伪标记来保护Web API免受CSRF攻击。防伪标记是在服务器端生成的,通过在服务器响应中将标记发送给客户端,并在客户端发起请求时验证该标记是否有效来确保请求来自于预期的来源。

在ASP.NET MVC中,可以使用AntiForgeryToken方法生成防伪标记,并在表单中插入该标记。然后在服务器端使用ValidateAntiForgeryToken属性来验证防伪标记的有效性。

如果Web API和前端应用程序位于不同的域上,可以考虑以下解决方案:

1. 使用CORS(跨源资源共享)来允许跨域请求,并在服务器端进行验证。

2. 将防伪标记作为请求头或查询参数发送到Web API,并在服务器端进行验证。

3. 使用其他身份验证方式,如基于令牌的身份验证,而不是依赖于防伪标记。

以上是解决CSRF问题的原因和方法。

0