登录在Chrome上正常运行,但在Safari(或我假设其他Webkit浏览器)上无效。登录后我收到此错误消息("您想要的更改被拒绝。也许您尝试更改了您无法访问的内容。"):
根据我的heroku日志,这就是发生的事情:
2016-12-07T14:14:23.778153+00:00 app[web.1]: Can't verify CSRF token authenticity
2016-12-07T14:14:23.778899+00:00 app[web.1]: Completed 422 Unprocessable Entity in 2ms (ActiveRecord: 0.0ms)
2016-12-07T14:14:23.785544+00:00 app[web.1]:
2016-12-07T14:14:23.785547+00:00 app[web.1]: ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
我相信我发送了正确的CSRF令牌,但似乎有些事情发生了故障。这是我目前的application_controller.rb
:
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
after_action :flash_to_headers
# this is so that json requests don't redirect without a user
before_action :authenticate_user!
# before_action :authenticate_user!, unless: request.format == :json
# before_action :user_needed, if: request.format == :json
before_action :set_paper_trail_whodunnit
before_action :set_global_search_variable
def set_global_search_variable
@q = Person.ransack(params[:q])
end
def user_needed
unless current_user
render json: { 'error' => 'authentication error' }, status: 401
end
end
def flash_to_headers
return unless request.xhr?
response.headers['X-Message'] = flash_message if flash_message
response.headers['X-Message-Type'] = flash_type.to_s if flash_type
flash.discard # don't want the flash to appear when you reload page
end
private
def flash_message
[:error, :warning, :notice].each do |type|
return flash[type] unless flash[type].blank?
end
nil
end
def flash_type
[:error, :warning, :notice].each do |type|
return type unless flash[type].blank?
end
nil
end
(将protect_from_forgery with:
更改为null_session
只会导致无限循环返回登录屏幕。)
This question引用了类似的问题,但没有讨论Devise的复杂性。据说Devise已经解决了这个问题,但它在某种程度上并没有在这里工作。许多these answers已有多年的历史,所以我不确定它们今天会有多相关。
我还尝试在实际的Devise Github回购中搜索错误,但我似乎无法在这些主题中获得任何建议。编辑应用程序控制器的建议很多,但很多时候似乎会破坏整个应用程序。
这个应用程序运行Ruby 2.2.5和Rails 4.2.7.1。更新到Rails 5是否有助于解决这个问题?
它还有一个用于制作管理员帐户的现有(也可能是hacky)覆盖;此人通过Devise注册,然后通过approved
shell中的另一个名为pqsl
的字段获得管理员访问权限。我不确定这是否相关。
该应用程序在Github,对于任何想看一眼的人: https://github.com/yamilethmedina/kimball
答案 0 :(得分:7)
事实证明,this answer解决了我的问题。毕竟它不在应用程序控制器中,而是在config/initializers/session_store.rb
。
这是我最初的session_store
:
Logan::Application.config.session_store :cookie_store, key: '_cutgroup_session', secure: (Rails.env.production? || Rails.env.staging?)
进一步研究后,我发现了这个建议:
Rails.application.config.session_store :cookie_store, key: "_rails_session_#{Rails.env}", domain: all
这仍然无效;但是,它会在日志中产生401错误(而不是422)并重定向回登录页面,而不是显示我在上面截屏的错误屏幕。
最后,我在Safari上为我工作的domain: all
的末尾删除了Rails.application.config.session_store :cookie_store, key: "_rails_session_#{Rails.env}"
部分(Cookie在浏览器的任何位置都没有被阻止)。现在,我可以在Heroku上部署项目时登录。
赏金是一个沉重的代价,但至少评论者帮助我澄清了我的想法并找到了解决方案!如果其他人遇到这个问题并提出了一个更好的问题,我会反过来投票,但我想我现在已经得到了它。
答案 1 :(得分:1)
尝试:
<强>控制器/ application.rb中强>
protect_from_forgery with: :null_session
和 覆盖您的设备控制器
<强> sessions_controller.rb 强>
class Users::SessionsController < Devise::SessionsController
skip_before_filter :verify_authenticity_token, :only => [:destroy]
end