Ember+Devise认证遇跨域问题:InvalidAuthenticityToken报错求助
解决无头Rails + Ember + Devise认证的InvalidAuthenticityToken跨域问题
我之前也碰到过几乎一模一样的问题,当时折腾了好一会儿才搞定,给你几个关键的排查和修复步骤:
1. 确保Rails的CORS配置完全正确
光装rack-cors插件只是第一步,必须在config/initializers/cors.rb里精确配置允许的源、请求方法,尤其是要开启凭证支持:
Rails.application.config.middleware.insert_before 0, Rack::Cors do allow do origins 'http://localhost:4200' # 严格匹配你的Ember服务地址 resource '*', headers: :any, methods: [:get, :post, :put, :patch, :delete, :options, :head], credentials: true # 这个是核心!跨域下Devise需要传递session cookie,必须开这个 end end
2. 调整Rails的CSRF防护策略
InvalidAuthenticityToken的本质是Rails默认会校验请求Origin和自身base_url是否一致,跨域场景下我们需要修改这个规则:
- 方案一:直接关闭Origin校验(适合开发环境)
在config/application.rb里添加:
config.action_controller.forgery_protection_origin_check = false
- 方案二:仅信任指定Origin(更安全,推荐生产环境用)
config.action_controller.permitted_cross_domain_origins = ['http://localhost:4200']
另外,在app/controllers/application_controller.rb里,确保CSRF防护适配API场景:
protect_from_forgery with: :exception, unless: -> { request.format.json? }
如果是纯无头API,也可以换成:null_session,但:exception模式更安全,只要我们正确配置了跨域信任。
3. Ember端的关键配置调整
虽然你装了CORS和CSP插件,但还要确保Ember Simple Auth和Devise适配器的配置正确:
- 先在
config/environment.js里更新CSP规则,允许连接到Rails服务:
ENV.contentSecurityPolicy = { 'connect-src': "'self' http://localhost:3000", 'img-src': "'self' data:", 'style-src': "'self' 'unsafe-inline'", 'script-src': "'self' 'unsafe-inline' 'unsafe-eval'" };
- 然后配置Ember Simple Auth的Devise适配器:
ENV['ember-simple-auth'] = { authenticationRoute: 'login', routeAfterAuthentication: 'dashboard', routeIfAlreadyAuthenticated: 'dashboard', authorizer: 'authorizer:devise' }; ENV['ember-simple-auth-devise'] = { serverTokenEndpoint: 'http://localhost:3000/users/sign_in', identificationAttributeName: 'email' // 要和你Devise用户模型的字段匹配 };
最后,确保Ember的数据适配器能正确携带CSRF Token,在app/adapters/application.js里:
import DS from 'ember-data'; import DataAdapterMixin from 'ember-simple-auth/mixins/data-adapter-mixin'; export default DS.JSONAPIAdapter.extend(DataAdapterMixin, { host: 'http://localhost:3000', namespace: '', // 如果你Rails API有前缀(比如/api)就填这里 authorizer: 'authorizer:devise', headers: function() { return { 'X-CSRF-Token': this.get('session.data.authenticity_token') }; }.property('session.data.authenticity_token') });
4. 别忘了重启服务!
很多时候配置修改后,Rails和Ember的开发服务器都需要完全重启才能生效,这个小细节很容易被忽略。
如果还是没解决,打开浏览器开发者工具的网络面板,检查这几个关键点:
- 请求头里有没有
Origin: http://localhost:4200和X-CSRF-Token - 响应头里有没有
Access-Control-Allow-Origin: http://localhost:4200和Access-Control-Allow-Credentials: true
这些信息能帮你快速定位问题出在Rails配置还是Ember端。
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

