我很難理解並正確實施用戶身份驗證在API中。換句話說,我很難理解Grape API與前端框架(如Backbone.js,AngularJS或Ember.js)的集成。葡萄和設計的用戶身份驗證
我試圖擺動所有不同的方法,並閱讀了很多關於這個,但谷歌回報我真正不好的資源,在我看來,就像沒有真正好的文章在這個主題上 - Rails和用戶身份驗證與設計和前端框架。
我會描述我目前的關鍵點,希望你能爲我的實施提供一些反饋意見,也許可以讓我指出正確的方向。
當前實現
我有後臺Rails的REST API具有以下的Gemfile(我會故意縮短所有文件代碼)
gem 'rails', '4.1.6'
gem 'mongoid', '~> 4.0.0'
gem 'devise'
gem 'grape'
gem 'rack-cors', :require => 'rack/cors'
我目前的實施只有使用API以下路線(routes.rb):
api_base /api API::Base
GET /:version/posts(.:format)
GET /:version/posts/:id(.:format)
POST /:version/posts(.:format)
DELETE /:version/posts/:id(.:format)
POST /:version/users/authenticate(.:format)
POST /:version/users/register(.:format)
DELETE /:version/users/logout(.:format)
我創建具有以下模型user.rb
class User
include Mongoid::Document
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
field :email, type: String, default: ""
field :encrypted_password, type: String, default: ""
field :authentication_token, type: String
before_save :ensure_authentication_token!
def ensure_authentication_token!
self.authentication_token ||= generate_authentication_token
end
private
def generate_authentication_token
loop do
token = Devise.friendly_token
break token unless User.where(authentication_token: token).first
end
end
end
以我控制器我創建下面的文件夾結構:controllers-> API-> V1和我有創建以下共享模塊身份驗證(authentication.rb)
module API
module V1
module Authentication
extend ActiveSupport::Concern
included do
before do
error!("401 Unauthorized", 401) unless authenticated?
end
helpers do
def warden
env['warden']
end
def authenticated?
return true if warden.authenticated?
params[:access_token] && @user = User.find_by(authentication_token: params[:access_token])
end
def current_user
warden.user || @user
end
end
end
end
end
end
所以每次當我想確保,我的資源將與認證令牌被調用,我可以簡單地通過調用補充一點:include API::V1::Authentication
的葡萄資源:
module API
module V1
class Posts < Grape::API
include API::V1::Defaults
include API::V1::Authentication
現在我有另一個葡萄資源稱爲Users(users.rb),在這裏我實現了用於認證,註冊和註銷的方法(我認爲我在這裏將蘋果與梨混合在一起,並且我應該將登錄/註銷過程提取到另一個Grape資源 - 會話中)。
module API
module V1
class Users < Grape::API
include API::V1::Defaults
resources :users do
desc "Authenticate user and return user object, access token"
params do
requires :email, :type => String, :desc => "User email"
requires :password, :type => String, :desc => "User password"
end
post 'authenticate' do
email = params[:email]
password = params[:password]
if email.nil? or password.nil?
error!({:error_code => 404, :error_message => "Invalid email or password."}, 401)
return
end
user = User.find_by(email: email.downcase)
if user.nil?
error!({:error_code => 404, :error_message => "Invalid email or password."}, 401)
return
end
if !user.valid_password?(password)
error!({:error_code => 404, :error_message => "Invalid email or password."}, 401)
return
else
user.ensure_authentication_token!
user.save
status(201){status: 'ok', token: user.authentication_token }
end
end
desc "Register user and return user object, access token"
params do
requires :first_name, :type => String, :desc => "First Name"
requires :last_name, :type => String, :desc => "Last Name"
requires :email, :type => String, :desc => "Email"
requires :password, :type => String, :desc => "Password"
end
post 'register' do
user = User.new(
first_name: params[:first_name],
last_name: params[:last_name],
password: params[:password],
email: params[:email]
)
if user.valid?
user.save
return user
else
error!({:error_code => 404, :error_message => "Invalid email or password."}, 401)
end
end
desc "Logout user and return user object, access token"
params do
requires :token, :type => String, :desc => "Authenticaiton Token"
end
delete 'logout' do
user = User.find_by(authentication_token: params[:token])
if !user.nil?
user.remove_authentication_token!
status(200)
{
status: 'ok',
token: user.authentication_token
}
else
error!({:error_code => 404, :error_message => "Invalid token."}, 401)
end
end
end
end
end
end
我意識到,我在這裏一噸的代碼,它可能沒有什麼意義,但是這是我現在有,我能夠使用authentication_token
針對我的API調用它們由模塊保護Authentication
。
我覺得這個解決方案不好,但我真的很想找到更簡單的方法來通過API實現用戶身份驗證。我有幾個問題,我列在下面。
問題
- 你覺得這種實現是很危險的,如果是的話,爲什麼呢? - 我認爲這是因爲使用了一個令牌。有沒有辦法改善這種模式?我也看到了具有到期時間等的單獨模型
Token
的實現。但我認爲這幾乎就像重新發明輪子,因爲爲此我可以實現OAuth2。我想有更輕的解決方案。 - 爲身份驗證創建新模塊並將其僅包含到需要它的資源中是一種很好的做法?
- 你知道關於這個主題的任何好教程 - 實現 Rails + Devise + Grape嗎?另外,你是否知道開源的Rails項目有哪些好的 ?
- 我該如何使用更安全的不同方法來實現它?
我很抱歉這麼長的帖子,但我希望更多的人有同樣的問題,這可能會幫助我找到更多的答案在我的問題。
真的,沒有人在做同樣的事情?或者其閱讀時間太長?我的天啊.... – 2014-10-29 18:01:20