我有一个使用devise for auth的rails api设置和前端的backbone.js。我能够让用户注册并登录,但我无法向api发送后续请求。我需要在签名后为每个请求附加一个身份验证令牌和一个电子邮件地址,以便提出进一步的请求,但我不知道该怎么做。
我的应用程序流程就像这样
每次请求发送令牌和电子邮件都是我遇到的问题。如何将其附加到骨干网中的请求?
我应该将它添加到http标头中,就像我使用csrf令牌一样吗?
到目前为止,这是我的设置。
带过滤器的Api控制器
class ApiController < ApplicationController
respond_to :json
before_filter :authenticate_user_from_token!
# This is Devise's authentication
before_filter :authenticate_api_v1_user!
private
def authenticate_user_from_token!
user_email = params[:email].presence
user = user_email && User.find_by_email(user_email)
if user && Devise.secure_compare(user.authentication_token, params[:token])
sign_in user, store: false
end
end
end
会话控制器
module Api
module V1
class SessionsController < Devise::SessionsController
skip_before_filter :authenticate_user!, only: :create
after_action :set_csrf_header, only: [:new, :create, :destroy]
def new
render nothing: true
end
def create
user = User.find_for_database_authentication(:email => params[:email])
if user && user.valid_password?(params[:password])
user.ensure_authentication_token # make sure the user has a token generated
render :json => { :user => user }, :status => :created
else
return invalid_login_attempt
end
end
def destroy
# expire auth token
user = User.where(:authentication_token => params[:authentication_token]).first
user.reset_authentication_token!
render :json => { :message => ["Session deleted."] }, :success => true, :status => :ok
end
private
def invalid_login_attempt
warden.custom_failure!
render :json => { :errors => ["Invalid email or password."] }, :success => false, :status => :unauthorized
end
def set_csrf_header
response.headers['X-CSRF-Token'] = form_authenticity_token
end
def form_authenticity_token
session[:_csrf_token] ||= SecureRandom.base64(32)
end
end
end
end
覆盖backbone.sync以设置csrf标头
require([
'backbone',
'router',
'app',
'jquery.mobile',
'google',
'models/session_model'
], function(Backbone, Router, AppView, JQMobile, google) {
window.Droppin = window.Droppin || {};
// overide backbone.sync
Backbone._sync = Backbone.sync;
Backbone.sync = function(method, model, options) {
if (!options.noCSRF) {
var beforeSend = options.beforeSend;
// Set X-CSRF-Token HTTP header
options.beforeSend = function(xhr) {
var token = Droppin.csrfToken;
if (token) xhr.setRequestHeader('X-CSRF-Token', token);
// this will include session information in the requests
xhr.withCredentials = true;
if (beforeSend) return beforeSend.apply(this, arguments);
};
}
var complete = options.complete;
options.complete = function(jqXHR, textStatus) {
// If response includes CSRF token we need to remember it
var token = jqXHR.getResponseHeader('X-CSRF-Token')
if (token) Droppin.csrfToken = token;
model.trigger('sync:end');
if (complete) complete(jqXHR, textStatus);
};
// Serialize data, optionally using paramRoot
if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
options.contentType = 'application/json';
data = JSON.stringify(options.attrs || model.toJSON(options));
if (model.paramRoot) {
data = {};
data[model.paramRoot] = model.toJSON(options);
} else {
data = model.toJSON();
}
options.data = JSON.stringify(data);
}
return Backbone._sync(method, model, options);
};
Backbone.history.start();
new AppView();
new Router();
});
答案 0 :(得分:0)
您可以全局覆盖所有jquery ajax请求,以在标题中包含某些内容。