rtc*_*oms 19 ruby-on-rails csrf devise rails-api ruby-on-rails-4
我正在使用devise(最新版本 - 3.2.0)rails(最新版本 - 4.0.1)
我正在进行简单的身份验证(没有ajax或api)并且收到CSRF真实性令牌的错误.检查下面的POST请求
started POST "/users/sign_in" for 127.0.0.1 at 2013-11-08 19:48:49 +0530
Processing by Devise::SessionsController#create as HTML
Parameters: {"utf8"=>"?",
"authenticity_token"=>"SJnGhXXUXjncnPhCdg3muV2GYCA8CX2LVFV78pqddD4=", "user"=>
{"email"=>"a@a.com", "password"=>"[FILTERED]", "remember_me"=>"0"},
"commit"=>"Sign in"}
Can't verify CSRF token authenticity
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."email" =
'a@a.com' LIMIT 1
(0.1ms) begin transaction
SQL (0.4ms) UPDATE "users" SET "last_sign_in_at" = ?, "current_sign_in_at" = ?,
"sign_in_count" = ?, "updated_at" = ? WHERE "users"."id" = 2 [["last_sign_in_at", Fri,
08 Nov 2013 14:13:56 UTC +00:00], ["current_sign_in_at", Fri, 08 Nov 2013 14:18:49 UTC
+00:00], ["sign_in_count", 3], ["updated_at", Fri, 08 Nov 2013 14:18:49 UTC +00:00]]
(143.6ms) commit transaction
Redirected to http://localhost:3000/
Completed 302 Found in 239ms (ActiveRecord: 144.5ms | Search: 0.0ms)
Run Code Online (Sandbox Code Playgroud)
根网址指向home#new,就像
class HomeController < ApplicationController
before_action :authenticate_user!
def index
end
end
Run Code Online (Sandbox Code Playgroud)
Sign_in页面生成的html视图如下:
元标记
<meta content="authenticity_token" name="csrf-param" />
<meta content="aV+d7Z55XBJF2VtyL8V3zupR3OwhaQ6UHNtlQLBQf5Y=" name="csrf-token" />
Run Code Online (Sandbox Code Playgroud)形成
<form accept-charset="UTF-8" action="/users/sign_in" class="new_user" id="new_user"
method="post">
<div style="margin:0;padding:0;display:inline">
<input name="utf8" type="hidden" value="✓" />
<input name="authenticity_token" type="hidden
value="aV+d7Z55XBJF2VtyL8V3zupR3OwhaQ6UHNtlQLBQf5Y=" />
</div>
<div><label for="user_email">Email</label><br />
<input autofocus="autofocus" id="user_email" name="user[email]" type="email" value="" />
</div>
<div><label for="user_password">Password</label><br />
<input id="user_password" name="user[password]" type="password" /></div>
<div><input name="user[remember_me]" type="hidden" value="0" />
<input id="user_remember_me" name="user[remember_me]" type="checkbox" value="1" />
<label for="user_remember_me">Remember me</label></div>
<div><input name="commit" type="submit" value="Sign in" /></div>
</form>
Run Code Online (Sandbox Code Playgroud)身份验证请求甚至更新了last_sign_in_at和sign_in_count值,但是当我尝试current_user在控制器中访问它时,它就是nil.
据我说它实际上并没有登录user.但接下来的问题是"为什么它在表中更新last_sign_in_at/ sign_in_count价值user?"
Jas*_*abe 10
当CSRF令牌不正确时,Rails将不会读取或对会话进行任何更新.它仍将执行控制器指定的任何其他操作,这解释了为什么您看到数据库更新但最终未登录.
我注意到日志和页面中的authenticity_token不匹配.我意识到这可能是因为您捕获了不同的请求,但是您应该检查页面上的那个请求是否与日志中的请求相匹配.我还假设您在视图中使用了正确的标记,每次都会生成不同的authenticity_token,而不仅仅是对HTML输入进行硬编码.
您是否看到与设计无关的表格存在同样的问题?如果没有,作为解决方法,您可以使用控制器中的以下代码免除CSRF检查中的操作:
protect_from_forgery except: :sign_in
Run Code Online (Sandbox Code Playgroud)
对你的登录行动进行CSRF攻击的可能性对我来说似乎很遥远(<-pun).
此外,如果它只是设计,那么我建议你提交一个问题,你已经完成了.
小智 6
在应用程序控制器上添加它(这适用于 Rails 5)
protect_from_forgery unless: -> { request.format.json? }
Run Code Online (Sandbox Code Playgroud)
将此添加到设计会话控制器
skip_before_action :verify_authenticity_token, only: [:create]
Run Code Online (Sandbox Code Playgroud)
用 curl 试试
curl -X POST -v -H 'Content-Type: application/json' http://0.0.0.0:3000/users/sign_in -d '{"user" : {"email": "name@mail.com", "password": "secret" }}'
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11746 次 |
| 最近记录: |