Rails 3:带有form_tag的CSRF

时间:2013-11-26 18:43:59

标签: ruby-on-rails devise csrf

快速背景

我的模型中有facility has_many managersrelationships。关系模型包含一个附加属性admin,它是一个布尔值。然后,对于每个设施,我有一个页面,允许管理员/某些用户将managers标记为admin。他们通过复选框执行此操作。我正在为管理人员使用设计。一切都像这个轨道广播的前2分钟一样完成:

http://railscasts.com/episodes/165-edit-multiple-revised?view=comments

问题(S)

问题是,当我提交form_tag时,我得到:

1。警告:无法验证CSRF令牌真实性

2. 然后重置我的用户会话(让我退出设计),所以我必须重新登录才能继续工作。

如果我从应用程序控制器中删除protect from forgery,一切都会顺利进行,但显然我不希望这样做是我的修复。

那么,如何使用form_tag避免此CSFR问题?

表格(已更新)

<%= form_tag admin_relationships_path, method: :put do %>
  <table>
    <tr>
    <th></th>
    <th>Person Name</th>
    <th>Admin</th>
    </tr>

<% @relationships.each do |relationship| %>
   <tr>
   <td><%= check_box_tag "relationship_ids[]", relationship.id %></td>
   **<%= hidden_field_tag :authenticity_token, form_authenticity_token %>**        
   <td><%= User.find(relationship.user_id).full_name %></td>
   <td><%= relationship.admin ? "Yes" : "No" %></td>

   <td><%= link_to 'Remove', relationship, method: :delete, **remote: true** %></td>

   </tr>
 <% end %>
  </table>

   <%= submit_tag "Make Checked Admins" %>
 <% end %>

控制者。

class RelationshipsController < ApplicationController

  def destroy
    @relationship = Relationship.find(params[:id])
    @relationship.destroy

    respond_to do |format|
      format.html { redirect_to "/facilities/1679/invite", notice: " Manager has been deleted." }
      format.json { head :no_content }
  end
end

日志。

Started DELETE "/relationships/52" for 127.0.0.1 at 2013-11-26 14:30:11 -0500
Processing by RelationshipsController#destroy as JS
Parameters: {"id"=>"52"}
WARNING: Can't verify CSRF token authenticity
  User Load (0.3ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 38 LIMIT 1
  (0.1ms)  BEGIN
  (0.1ms)  COMMIT
 Relationship Load (0.2ms)  SELECT `relationships`.* FROM `relationships` WHERE `relationships`.`id` = 52 LIMIT 1
  (0.1ms)  BEGIN
 SQL (0.2ms)  DELETE FROM `relationships` WHERE `relationships`.`id` = 52
  (0.4ms)  COMMIT
 Redirected to http://localhost:3000/facilities/1679/invite
 Completed 302 Found in 10ms (ActiveRecord: 1.6ms)


 Started DELETE "/facilities/1679/invite" for 127.0.0.1 at 2013-11-26 14:30:11 -0500

 ActionController::RoutingError (No route matches [DELETE] "/facilities/1679/invite"):

请求标题:

AcceptAccept-EncodingAccept-LanguageConnectionCookieHostOriginRefererUser-AgentX-Requested-With

答案

如下面提到的海报,我的CSFR令牌未在页面上收到。虽然,我的应用程序布局和管理布局中有<%= csrf_meta_tag %>,而我实际上是在渲染应用程序布局,但表单是在Devise页面上。

所以我需要将<%= csrf_meta_tag %>代码放入devise.html.erb.您可以在下面找到问题排查。

2 个答案:

答案 0 :(得分:3)

请确保在头部中的应用程序布局中有这个:

<%= csrf_meta_tag %>

或者您表单中隐藏的字段:

<%= hidden_field_tag :authenticity_token, form_authenticity_token %>

答案 1 :(得分:3)

尝试将此添加到aplication.js:

$.ajaxSetup({
  headers: {
    'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
  }
});

在这里回答:WARNING: Can't verify CSRF token authenticity rails