ActionController :: InvalidAuthenticityToken


148

ด้านล่างเป็นข้อผิดพลาดที่เกิดจากแบบฟอร์มในแอปพลิเคชัน Rails ของฉัน:

Processing UsersController#update (for **ip** at 2010-07-29 10:52:27) [PUT]
  Parameters: {"commit"=>"Update", "action"=>"update", "_method"=>"put", "authenticity_token"=>"ysiDvO5s7qhJQrnlSR2+f8jF1gxdB7T9I2ydxpRlSSk=", **more parameters**}

ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):

นี้เกิดขึ้นทุกครั้งที่ไม่ได้getแจ้งความประสงค์และที่คุณเห็นauthenticity_tokenจะมี

คำตอบ:


207

ฉันมีปัญหาเดียวกัน แต่มีหน้าซึ่งถูกแคชหน้า หน้าถูกบัฟเฟอร์ด้วยโทเค็นของแท้ที่เก่าแล้วและการดำเนินการทั้งหมดโดยใช้วิธีการโพสต์ / วาง / ลบที่ได้รับการยอมรับว่าเป็นความพยายามปลอมแปลง ข้อผิดพลาด (422 ไม่สามารถประมวลผลได้) ถูกส่งคืนไปยังผู้ใช้

ทางออกสำหรับ Rails 3:
เพิ่ม:

 skip_before_filter :verify_authenticity_token  

หรือตามที่ "sagivo" ชี้ให้เห็นใน Rails 4 เพิ่ม:

 skip_before_action :verify_authenticity_token

บนหน้าเว็บที่ทำการแคช

ตามที่ @toobulkeh แสดงความคิดเห็นว่านี่ไม่ใช่ช่องโหว่ใน:index, :showการกระทำ, แต่ระวังการใช้สิ่งนี้กับ:put, :postการกระทำ

ตัวอย่างเช่น:

 caches_page :index, :show  
 skip_before_filter :verify_authenticity_token, :only => [:index, :show]

การอ้างอิง: http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection/ClassMethods.html

หมายเหตุเพิ่มโดย barlop- Rails 4.2 คัดค้าน skip_before_filter เพื่อสนับสนุน skip_before_action https://guides.rubyonrails.org/4_2_release_notes.html "การใช้งานตระกูล * _filter ได้ถูกลบออกจากเอกสารประกอบ ตระกูลของวิธีการ "

สำหรับRails 6 (ตามที่ "collimarco" ชี้ให้เห็น) คุณสามารถใช้skip_forgery_protectionและมันปลอดภัยที่จะใช้สำหรับ REST API ที่ไม่ได้ใช้ข้อมูลเซสชัน


3
เป็นไปไม่ได้ที่ฉันไม่รู้จักcaches_pageก่อนโพสต์ของคุณ แต่ฉันจะตรวจสอบcaches_pageออกขอบคุณ
Nikita Rybak

7
ในราง 4skip_before_action :verify_authenticity_token
Sagiv Ofek

88
นี่เป็นช่องโหว่หรือไม่
quantumpotato

6
นี่ไม่ใช่ช่องโหว่ของ:index, :showการกระทำ แต่ระวังการ:put, :postกระทำนี้!
toobulkeh

14
แม้ว่าฉันจะยอมรับว่าบางครั้งคุณก็จำเป็นต้องใช้สิ่งนี้ (เช่นอาจจะครั้งหนึ่งในชีวิต) แต่คุณต้องตระหนักว่าคุณกำลังแก้ไขความปลอดภัยโดยการปิดการใช้งานความปลอดภัย ไม่แนะนำ
เทียบเท่า

77

สำหรับฉันสาเหตุของปัญหานี้ภายใต้ Rails 4 หายไป

<%= csrf_meta_tags %>

จัดเรียงในแอปพลิเคชันหลักของฉัน ฉันลบมันโดยไม่ได้ตั้งใจเมื่อฉันเขียนเค้าโครงของฉันอีกครั้ง

หากนี่ไม่ได้อยู่ในเลย์เอาต์หลักคุณจะต้องใช้มันในหน้าใด ๆ ที่คุณต้องการให้เปิดโทเค็น CSRF


2
เรากำลังได้รับข้อผิดพลาดนี้เช่นกัน แต่มันถูกขัดจังหวะ นี่อาจเป็นเหตุผลหรือไม่ส่งผลกระทบต่อการร้องขอทุกครั้งที่มีข้อผิดพลาดหรือไม่?
Ryan-Neal Mes

@ Ryan-NealMes หากแม่แบบของคุณหายไปจากบรรทัดนั้นคุณจะได้รับข้อผิดพลาด ดังนั้นจึงมีความเป็นไปได้ที่เทมเพลตของคุณจะมีบางอย่างและบางอันไม่มี
James McMahon

1
@JamesMcMahon ขอบคุณฉันคิดว่ากรณีของฉันมีสาเหตุมาจากผู้ใช้ล้างคุกกี้หรือปิดกั้นคุกกี้ เรียนรู้การโหลดจากคำถามนี้!
Ryan-Neal Mes

61

มีสาเหตุหลายประการสำหรับข้อผิดพลาดนี้ (เกี่ยวข้องกับ Rails 4)

1. ตรวจสอบ<%= csrf_meta_tags %>การนำเสนอในเค้าโครงหน้า

2. ตรวจสอบโทเค็นของแท้จะถูกส่งด้วยการโทร AJAX หากใช้ตัวform_forช่วยที่มีตัวเลือกremote: trueถ้าไม่คุณสามารถรวมบรรทัดที่<%= hidden_field_tag :authenticity_token, form_authenticity_token %>มีบล็อกแบบฟอร์ม

3. หากมีการส่งคำขอจากหน้าแคชให้ใช้การแคชส่วนเพื่อแยกส่วนของหน้าที่ส่งคำขอbutton_toเป็นต้นมิฉะนั้นโทเค็นจะล้าสมัย / ไม่ถูกต้อง

ฉันจะลังเลที่จะลบล้างการป้องกัน csrf ...


csrf_meta_tags ควรอยู่ใน <head> หรือไม่ ฉันจะแน่ใจได้อย่างไรว่ามันจะไม่ขัดแย้งกับ turbolinks
ประกาย

37

เพียงแค่เพิ่มauthenticity_tokenในรูปแบบคงที่สำหรับฉัน

<%= hidden_field_tag :authenticity_token, form_authenticity_token %>

3
Rails ควรจะส่งโทเค็นเป็นค่าเริ่มต้น เราไม่ต้องการระบุอย่างชัดเจน ฉันรู้สึกว่าโทเค็นมีการเปลี่ยนแปลงอย่างใดในสถานการณ์นี้ที่นี่
Abhi

1
อย่างไรก็ตามหากคุณสร้างแบบฟอร์มโดยไม่ใช้ผู้ช่วยเหลือคุณควรใส่แบบฟอร์มด้วยตนเอง
AndréGuimarães Sakata

30

โทเค็นของแท้เป็นค่าสุ่มที่สร้างขึ้นในมุมมองของคุณเพื่อพิสูจน์ว่าคำขอถูกส่งมาจากแบบฟอร์มบนเว็บไซต์ของคุณไม่ใช่ที่อื่น สิ่งนี้จะช่วยป้องกันการโจมตี CSRF:

http://en.wikipedia.org/wiki/Cross-site_request_forgery

ตรวจสอบว่าลูกค้า / IP นั้นเป็นใครดูเหมือนว่าพวกเขากำลังใช้ไซต์ของคุณโดยไม่โหลดมุมมองของคุณ

หากคุณต้องการแก้ปัญหาเพิ่มเติมคำถามนี้เป็นจุดเริ่มต้นที่ดี: ทำความเข้าใจโทเค็นของแท้สำหรับ Rails

แก้ไขเพื่ออธิบาย: หมายความว่าพวกเขากำลังเรียกการกระทำเพื่อประมวลผลการส่งแบบฟอร์มของคุณโดยไม่ต้องแสดงฟอร์มของคุณบนเว็บไซต์ของคุณ สิ่งนี้อาจเป็นอันตราย (เช่นโพสต์ความคิดเห็นสแปม) หรืออาจระบุว่าลูกค้าพยายามใช้ API บริการเว็บของคุณโดยตรง คุณเป็นคนเดียวที่สามารถตอบได้โดยธรรมชาติของผลิตภัณฑ์ของคุณและวิเคราะห์คำขอของคุณ


1
ขอบคุณ แต่ฉันรู้อยู่แล้วว่าโทเค็นของแท้คืออะไร ตรวจสอบว่าลูกค้า / IP นั้นเป็นใครดูเหมือนว่าพวกเขากำลังใช้ไซต์ของคุณโดยไม่โหลดมุมมองของคุณ ขออภัย "ไม่โหลดการดู" หมายถึงอะไร
Nikita Rybak

1
ฉันหมายความว่าบางคน (อาจเป็นผู้ส่งสแปม) สามารถส่งข้อมูลไปยังแบบฟอร์มของคุณได้โดยไม่ต้องผ่านส่วนต่อประสานผู้ใช้ของแอปพลิเคชันของคุณ เป็นไปได้ที่จะทำสิ่งนี้โดยใช้โปรแกรมบรรทัดคำสั่งเช่น curl เป็นต้น
John Topley

จอห์นพูดถูก หมายความว่าพวกเขากำลังเรียกร้องให้ดำเนินการส่งแบบฟอร์มของคุณโดยไม่ต้องแสดงฟอร์มของคุณบนเว็บไซต์ของคุณ สิ่งนี้อาจเป็นอันตราย (เช่นโพสต์ความคิดเห็นสแปม) หรืออาจเป็นการระบุว่าลูกค้าพยายามใช้ API บริการเว็บของคุณโดยตรง คุณเป็นคนเดียวที่สามารถตอบได้โดยธรรมชาติของผลิตภัณฑ์ของคุณและวิเคราะห์คำขอของคุณ
Winfield

ตกลงฉันเข้าใจผิดความคิดเห็นของ Winfield ฉันคิดว่าแอพไม่ได้รับการกำหนดค่าให้ 'โหลดมุมมองของฉัน' เมื่อฉันใช้เบราว์เซอร์
Nikita Rybak

1
ฉันยังมีความคิดอื่นคำขอเหล่านี้มีโทเค็น แต่ก็ไม่ถูกต้อง สิ่งนี้อาจเกิดจากการแคชหน้าการแสดงผลแบบฟอร์มของคุณหรืออย่างอื่นที่ทำให้รูปแบบรุ่นเก่าอาจเกิดขึ้น
Winfield

26

ActionController::InvalidAuthenticityTokenอาจเกิดจากพร็อกซีย้อนกลับที่กำหนดค่าผิด Request origin does not match request base_urlเป็นกรณีนี้ถ้าในกองติดตามคุณจะได้รับบรรทัดมองเช่น

เมื่อใช้ reverse proxy (เช่น nginx) เป็นผู้รับสำหรับการร้องขอ HTTPS และส่งคำขอที่ไม่ได้เข้ารหัสไปยังแบ็กเอนด์ (เช่นแอพ Rails) แบ็กเอนด์ (เฉพาะ: แร็ค) คาดว่าส่วนหัวบางส่วนที่มีข้อมูลเพิ่มเติมเกี่ยวกับคำขอไคลเอนต์ดั้งเดิม เพื่อให้สามารถใช้งานการประมวลผลและมาตรการความปลอดภัยต่าง ๆ ได้

รายละเอียดเพิ่มเติมมีอยู่ที่นี่: https://github.com/rails/rails/issues/22965

TL; DR: โซลูชันคือการเพิ่มส่วนหัวบางส่วน:

upstream myapp {
  server              unix:///path/to/puma.sock;
}

location / {
  proxy_pass        http://myapp;
  proxy_set_header  Host $host;
  proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header  X-Forwarded-Proto $scheme;
  proxy_set_header  X-Forwarded-Ssl on; # Optional
  proxy_set_header  X-Forwarded-Port $server_port;
  proxy_set_header  X-Forwarded-Host $host;
}

ว้าวฉันได้ค้นหาวิธีแก้ปัญหานี้มา 3 ชั่วโมงแล้วและนี่ก็เป็นเช่นนั้นขอบคุณ!
evexoio

ขอบคุณมาก ๆ ที่พยายามแก้ปัญหานี้ทางรถไฟ 6 ชั่วโมง
Joe Half Face

18

สายเกินไปที่จะตอบ แต่ฉันพบวิธีแก้ปัญหา

เมื่อคุณกำหนดรูปแบบ html ของคุณเองคุณจะพลาดสายโทเค็นการตรวจสอบความถูกต้องที่ควรส่งไปยังตัวควบคุมด้วยเหตุผลด้านความปลอดภัย แต่เมื่อคุณใช้ตัวช่วยสร้าง Rails เพื่อสร้างฟอร์มคุณจะได้รับสิ่งต่อไปนี้

<form accept-charset="UTF-8" action="/login/signin" method="post">
  <div style="display:none">
    <input name="utf8" type="hidden" value="&#x2713;">
    <input name="authenticity_token" type="hidden" 
      value="x37DrAAwyIIb7s+w2+AdoCR8cAJIpQhIetKRrPgG5VA=">
    .
    .
    .
  </div>
</form>

ดังนั้นทางออกของปัญหาคือการเพิ่มเขตข้อมูล authenticity_token หรือใช้ตัวช่วยสร้างรูปแบบรางแทนจากนั้นจึงนำออกลดระดับหรืออัพเกรดราง


9

หากคุณได้ทำการrake rails:updateเปลี่ยนแปลงหรือเมื่อเร็ว ๆ นี้ของคุณconfig/initializers/session_store.rbนี่อาจเป็นอาการของคุกกี้เก่าในเบราว์เซอร์ หวังว่าสิ่งนี้จะทำในการพัฒนา / ทดสอบ (สำหรับฉัน) และคุณสามารถล้างคุกกี้เบราว์เซอร์ทั้งหมดที่เกี่ยวข้องกับโดเมนที่เป็นปัญหา

หากนี่เป็นการผลิตและคุณเปลี่ยนkeyให้ลองเปลี่ยนกลับไปใช้คุกกี้เก่า (<- แค่การเก็งกำไร)


ใช่ สำหรับฉันการมี session_store.rb ว่างเปล่าทำให้เกิดข้อผิดพลาด
lafeber

6

ฉันมีปัญหากับการโทรจาวาสคริปต์ ฉันแก้ไขด้วยเพียงต้องการ jquery_ujs เป็นไฟล์ application.js


ใช่ถูกต้องฉันมีปัญหานี้และฉันเพิ่ม jquery_ujs ในแอปพลิเคชัน js มันได้ผล
Abhi

3

เรามีปัญหาเดียวกัน แต่สังเกตว่าเป็นเพียงคำขอที่ใช้ http: // แต่ไม่ใช่กับ https: // สาเหตุมีsecure: trueไว้สำหรับ session_store:

Rails.application.config.session_store(
  :cookie_store,
  key: '_foo_session',
  domain: '.example.com',
  secure: true
)

แก้ไขโดยใช้ HTTPS ~ ทุกที่ :)


ฉันพบสิ่งนี้เมื่อใช้rails s(ไม่ใช่ SSL) แทนจุดสิ้นสุด SSL ที่ฉันตั้งค่าไว้สำหรับการพัฒนา มันไม่ได้จนกว่าฉันจะอ่านความคิดเห็นของคุณว่าฉันรู้ว่าฉันกำลังทำอะไรอยู่ เมื่อฉันเปลี่ยนกลับไปใช้ SSL สิ่งต่างๆก็เริ่มทำงานอีกครั้ง ขอบคุณ!
Karl Wilbur

1
ฉันประสบปัญหานี้ในการพัฒนา แทนsecure: trueฉันเขียนsecure: !Rails.env.development?
รบกวน

1

สำหรับ rails 5 ควรใส่ protect_from_forgery prepend: trueมากกว่าที่จะข้ามverify_authentication_token


5
ทำไม? คุณสามารถเพิ่มการอ้างอิงได้หรือไม่?
kwerle


0

ฉันมีปัญหานี้และสาเหตุก็เพราะฉันคัดลอกและวางคอนโทรลเลอร์ในแอปของฉัน ฉันต้องการที่จะเปลี่ยนApplicationControllerเป็นApplicationController::Base


0

ฉันมีปัญหาเดียวกันบน localhost ฉันเปลี่ยนโดเมนสำหรับแอปแล้ว แต่ใน URL และไฟล์โฮสต์ยังคงมีโดเมนเดิมอยู่ อัปเดตไฟล์บุ๊คมาร์คและโฮสต์ของเบราว์เซอร์เพื่อใช้โดเมนใหม่และตอนนี้ทุกอย่างทำงานได้ดี


0

บางทีคุณมีการตั้งค่า NGINX สำหรับ HTTPS แต่ใบรับรองของคุณไม่ถูกต้อง ฉันเคยมีปัญหาที่คล้ายกันในอดีตและการเปลี่ยนเส้นทางจาก http ไปยัง https แก้ปัญหา


0

ฉันตรวจสอบว่า <% = csrf_meta_tags%> ปรากฏขึ้นและมีการล้างคุกกี้ในเบราว์เซอร์ที่ใช้งานได้สำหรับฉัน


0

การปฏิบัติตามคำแนะนำของ Chrome Lighthouse สำหรับการโหลดแอปพลิเคชันที่เร็วขึ้นฉันได้ทำการปรับ Javascript ของฉัน:

views/layout/application.html.erb

<%= javascript_include_tag 'application', 'data-turbolinks-track' => 'reload', async: true %>

สิ่งนี้ทำลายทุกสิ่งและได้รับข้อผิดพลาดของโทเค็นสำหรับฟอร์มระยะไกลของฉัน การลบการasync: trueแก้ไขปัญหา


0

คำตอบนี้เฉพาะเจาะจงมากกับ Ruby on Rails แต่หวังว่ามันจะช่วยใครซักคน

คุณต้องรวมโทเค็น CSRF กับทุกคำขอที่ไม่ใช่ GET หากคุณคุ้นเคยกับการใช้ JQuery Rails จะมีไลบรารีผู้ช่วยเหลือที่เรียกjquery-ujsว่าสร้างอยู่ด้านบนและเพิ่มฟังก์ชันการทำงานที่ซ่อนอยู่ หนึ่งในสิ่งที่มันจะรวมโทเค็น CSRF โดยอัตโนมัติในทุกajaxคำขอ ดูที่นี่

หากคุณเปลี่ยนไปจากมันเหมือนฉันคุณอาจพบว่าตัวเองมีข้อผิดพลาด คุณสามารถส่งโทเค็นด้วยตนเองหรือใช้ไลบรารีอื่นเพื่อช่วยคัดลอกโทเค็นจาก DOM ดูโพสต์นี้สำหรับรายละเอียดเพิ่มเติม


-1

ใน Rails 5 เราต้องเพิ่มโค้ด 2 บรรทัด

    skip_before_action :verify_authenticity_token
    protect_from_forgery prepend: true, with: :exception

-2

การติดตั้ง

gem 'remotipart' 

สามารถช่วย


3
แม้ว่านี่อาจเป็นคำตอบ แต่มันก็มีประโยชน์ที่จะรวมส่วนสำคัญของคำตอบและอธิบายว่าทำไม / ทำงานอย่างไร
Roy Lee

-15

แก้ไขปัญหาโดยการลดระดับเป็น 2.3.5 จาก 2.3.8 (รวมถึงปัญหา 'คุณกำลังถูกเปลี่ยนเส้นทาง' ที่น่าอับอาย)


@Flip อาจเป็นความคิดที่จะอัพเดทคำตอบที่ยอมรับหรือไม่
lafeber
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.