草庐IT

php - Laravel CSRF保护下的JQuery AJAX跨站请求

coder 2024-04-18 原文

我正在使用 Laravel(后端)和 ReactJS 与 JQuery(前端)构建一个类似于 CMS 的 Web 应用程序。

我决定将现有的 Web API 放入一个单独的域 (api.test.com),并且我的用户界面位于不同的域 (test.com)。

test.com 上,我向 api.test.com 发起 ajax 请求以修改服务器上的一些资源:

  $.ajax({
    url: "api.test.com",
    method: 'POST',
    data: {...}
    success: function (no) {
    // ...
    }
  });

当然,由于安全问题,这是非法的。但是,我可以配置我的网络服务器:

对于 Nginx:

  add_header Access-Control-Allow-Origin http://test.com;
  add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE;
  add_header Access-Control-Allow-Headers X-Requested-With,X-CSRF-TOKEN,X-XSRF-TOKEN;

完美解决了Access-Control-Allow-Origin问题,但是由于Laravel的CSRF保护又出现了另一个问题...

默认情况下,Laravel 要求请求中包含一个 CSRF token (POST、PUT...这将修改资源)。

在我的例子中,我必须在 api.test.com 而不是 test.com 上生成 csrf_token 因为不同的域不共享 token 。

我按照 Laravel 的用户指南将这些代码添加到我的前端:

  $.ajax({
    url: "api.test.com/token", // simply return csrf_token();
    method: "GET",
    success: function (token) {
      // Now I get the token
      _token = token;
    }.bind(this)
  });

并修改之前的请求实现:

  $.ajax({
    url: "api.test.com",
    method: 'POST',
    headers: {
      "X-CSRF-TOKEN": _token // Here I passed the token
    },
    data: {...}
    success: function (no) {
    // ...
    }
  });

但是 Laravel 响应状态代码 500。然后我检查了 VerifyCsrfToken.php:

protected function tokensMatch($request)
{
    $token = $request->input('_token') ?: $request->header('X-CSRF-TOKEN');
    if (!$token && $header = $request->header('X-XSRF-TOKEN')) {
        $token = $this->encrypter->decrypt($header);
    }
    // Log::info($request->session()->token() . " == $token");
    return Str::equals($request->session()->token(), $token);
}

我“POST”到的 $token 与原来的不同($request->session()->token()).

我发现在调用 $.ajax 时服务器上的验证 token 不同。

我尝试将两个请求放在同一个 session 中(通过更改 cookie),但这是不可能的。

我花了很多时间来解决这个问题,但没有解决。

有什么想法或解决方案吗?

谢谢, 米库兹

最佳答案

感谢您回答我的问题。我考虑过禁用对某些 URI 的 CSRF 保护,但我不想冒这些风险。

我的问题的关键点是 $.ajax 忘记在请求前携带 cookie,导致 token 验证失败。

现在我设置了 JQuery Ajax,让它在发出请求之前携带 cookie。

  $.ajaxSetup({
    xhrFields: { withCredentials: true }
  });

和 Nginx 配置:

  add_header Access-Control-Allow-Credentials true;

顺便说一句,没有必要在数据中包含 token :{}(Form)。

所有问题都解决了,对我来说非常有效。

关于php - Laravel CSRF保护下的JQuery AJAX跨站请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31457719/

有关php - Laravel CSRF保护下的JQuery AJAX跨站请求的更多相关文章

  1. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  2. jquery - 我的 jquery AJAX POST 请求无需发送 Authenticity Token (Rails) - 2

    rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送

  3. ruby - HTTP 请求中的用户代理,Ruby - 2

    我是Ruby的新手。我试过查看在线文档,但没有找到任何有效的方法。我想在以下HTTP请求botget_response()和get()中包含一个用户代理。有人可以指出我正确的方向吗?#PreliminarycheckthatProggitisupcheck=Net::HTTP.get_response(URI.parse(proggit_url))ifcheck.code!="200"puts"ErrorcontactingProggit"returnend#Attempttogetthejsonresponse=Net::HTTP.get(URI.parse(proggit_url)

  4. ruby-on-rails - 获取并发布相同匹配项的请求 - 2

    在我的路线文件中我有:match'graphs/(:id(/:action))'=>'graphs#(:action)'如果是GET请求(工作)或POST请求(不工作),我想匹配它我知道我可以使用以下方法在资源中声明POST请求:post'/'=>:show,:on=>:member但是我怎样才能为比赛做到这一点呢?谢谢。 最佳答案 如果你同时想要POST和GETmatch'graphs/(:id(/:action))'=>'graphs#(:action)',:via=>[:get,:post]编辑默认值可以设置如下match'g

  5. ruby-on-rails - 如何在 ActionController::TestCase 请求中设置内容类型 - 2

    我试图像这样在我的测试用例中执行获取:request.env['CONTENT_TYPE']='application/json'get:index,:application_name=>"Heka"虽然,它失败了:ActionView::MissingTemplate:Missingtemplatealarm_events/indexwith{:handlers=>[:builder,:haml,:erb,:rjs,:rhtml,:rxml],:locale=>[:en,:en],:formats=>[:html]尽管在我的Controller中我有:respond_to:html,

  6. ruby-on-rails - 这个 C 和 PHP 程序员如何学习 Ruby 和 Rails? - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我来自C、php和bash背景,很容易学习,因为它们都有相同的C结构,我可以将其与我已经知道的联系起来。然后2年前我学了Python并且学得很好,Python对我来说比Ruby更容易学。然后从去年开始,我一直在尝试学习Ruby,然后是Rails,我承认,直到现在我还是学不会,讽刺的是那些打着简单易学的烙印,但是对于我这样一个老练的程序员来说,我只是无法将它

  7. ruby - 如何测试 (rspec) 花费太长时间的 http 请求? - 2

    如果使用rspec请求花费的时间太长,我该如何测试行为?我正在考虑使用线程来模拟这个:describe"Test"doit"shouldtimeoutiftherequesttakestoolong"dolambda{thread1=Thread.new{#net::httprequesttogoogle.com}thread2=Thread.new{sleep(xxseconds)}thread1.jointhread2.join}.shouldraise_errorendend我想确保在第一次发出请求后,另一个线程“启动”,在这种情况下只是休眠xx秒。然后我应该期望请求超时,因为执

  8. ruby - Sinatra 路由中定义的全局变量是否在请求之间共享? - 2

    假设我有:get'/'do$random=Random.rand()response.body=$randomend如果我每秒有数千个请求到达/,$random是否会被共享并“泄漏”到上下文之外,或者它会像getblock的“本地”变量一样?我想如果它是在get'/'do的上下文之外定义的,它确实会被共享,但我想知道在ruby​​中是否有我不知道的$机制。 最佳答案 ThispartoftheSinatraREADMEaboutscopeisalwayshelpfultoread但是,如果您只需要为请求保留变量,那么我认为我建议使用

  9. ruby - 无法安装 ruby​​ 1.9.3 获取请求的 URL 不存在 - 2

    运行以下命令时:rvminstall1.9.3我得到以下输出:Error:therequestedURLdoesnotexist:ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-.tar.bz2我已将rvm更新到最新版本并输入rvmreload有什么想法吗? 最佳答案 URL应该是这样的:ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p194.tar.bz2尝试更新您的rvmrvmgethead然后安装1.9.3rvminstall1.9.3

  10. ruby-on-rails - 如何通过 HTTParty 通过 PUT 请求发送空数组? - 2

    我有一个具有“名称”属性和“标签”属性的照片类。我的目标是在Rails中实现一个更新功能,用输入的内容替换照片的标签。例如,如果我尝试PUT一个将“标签”设置为[]的JSON对象,我希望从照片中清除任何标签。但是,当我通过HTTParty提交一个空数组作为主体参数之一时,我相信HTTParty正在将[]翻译成nil。因此,我的Rails后端的photos#update端点没有接收到任何参数“tags”。我正在寻找一种方法让HTTParty不将[]转换为nil,因为我失去了从照片中删除标签的能力。 最佳答案 这是Rails4中的一个错

随机推荐