I'm writing a Rails 4 app that will expose an API for a mobile app that's yet to be developed. Users will authenticate using an e-mail and password from the mobile app.
While I've found quite a bit of information on the topic. It's hard to discern what's dated or non-optimal. I've read about HTTP Basic Auth, which doesn't seem too secure, and HTTP Token-based Auth, but I'm not sure on how to couple that with regular e-mail and password authentication (I'm using Devise by the way).
I'd just like to know what's the current best practice on how to implement this, so I'll be sure to be going the right way.
答案 0 :(得分:47)
从安全角度来看,重要的一点是将用户的电子邮件和密码更换为令牌一次,然后将该令牌用于后续请求。这是因为:
有很多方法可以通过不同程度的复杂性来实现这一目标。
这是一个非常新的教程,并且有一个全面的演练,用于在Rails中使用基于令牌的身份验证创建API(不使用Devise,但仍然与理解概念相关):https://labs.kollegorna.se/blog/2015/04/build-an-api-now/
答案 1 :(得分:5)
另一种选择是在您的设计模型中包含下面的模块,并将auth_token添加到您的表中。
module TokenAuthenticatable
extend ActiveSupport::Concern
included do
before_save :ensure_auth_token
end
module ClassMethods
def find_by_token(token)
find_by(auth_token: token)
end
end
def ensure_auth_token
self.auth_token = generate_auth_token if auth_token.blank?
end
private
def generate_auth_token
loop do
token = Devise.friendly_token
break token unless self.class.exists?(auth_token: token)
end
end
end
...
def login_user(params)
if params[:authentication]
@user = User.find_by(auth_token: params[:authentication])
if @user.nil?
render json: err('login user by token failed', ERR_USER_NOT_FOUND), status: :not_found
event('login_user_by_auth_failed', 'token', params[:authentication])
return
else
render status: :ok, json: @user
return
end
else
user = user.find_by(email: params[:email])
if user.nil?
event('login_user_failed_not_found', 'user_email', params[:email])
render json: err("login user not found #{params[:email]}", ERR_USER_NOT_FOUND), status: :not_found
return
end
if user.access_locked?
event('login_user_blocked', 'user_id', user.id)
render json: err("login user account is locked : #{user.id}", ERR_USER_LOCKED), status: :unauthorized
return
end
unless user.try(:valid_password?, params[:password])
event("login_user_password_does_not_match #{user.id}", 'user_id', user.id)
render json: err('login user password does not match', ERR_PASSWORD_NOT_MATCH), status: :unauthorized
return
end
event('login_user_succeeded', 'user_id', user.id)
@user= user
if @user.save
response.headers['authentication'] = @user.auth_token
render status: :ok, json: @user
return
else
render json: @user.errors, status: :unprocessable_entity
return
end
end
end
...
编辑:纠正了破译错误的错误
答案 2 :(得分:4)
@ Roma149这更多是个人偏好,但大多数刚开始使用Devise的人都是最容易的IMO。 OAuth2也是一个不错的选择。 更重要的是,您可以随时转到The Ruby Toolbox
那里有很多关于宝石的好信息,他们甚至会告诉你宝石的年龄和受欢迎程度。这也可以让你区分社区现在正在寻找什么样的宝石或者过时的东西。
请记住,在Ruby和Ruby On Rails中,并不总是更好的宝石,但最适合您的项目的是什么!
答案 3 :(得分:3)
Tiddle gem在仅限API的Ruby on Rails应用程序中为令牌身份验证提供Devise策略。它的主要功能是支持每个用户的多个令牌。