用户API认证登录到Web应用程序服务器 [英] API Authentication for user logged in to a Web App server
问题描述
我建立一个Web应用程序和单独的API使用Ruby on Rails(因此,如果他们想要用户可以与他人共享自己收集的数据)。用户可以登录的Web应用程序,并填写应发布到API服务器数据。
I am building a Web App and a separate API (so that users can share their collected data with someone if they want to) using Ruby on Rails. The users can log in on the web app and fill data that should be posted to the API Server.
这一切我已阅读到现在,我想我可以使用基于Cookie的身份验证,检查用户是否到Web应用程序登录。现在让我们假设用户希望将数据发布到API服务器。由于用户进行身份验证的Web应用程序服务器,应该如何post请求作出这样的API知道它是从谁在登录的特定用户获取数据。此外,如果用户想了解从API数据专用于他/她,应该如何GET请求来为此做?
From everything I have read till now, I guess that I can use cookie based authentication to check whether the user is logged in to the Web App. Now let's say that the user wants to post data to the API Server. Since the user is authenticated to the Web App Server, how should the post request be made so that the API knows that it is getting the data from the specific user who is logged in. Also if the user wants to get data from the API that is private to him/her, how should the get request be made for this purpose?
推荐答案
您可以考虑您的API授权的守门人宝石。我认为它还是决定离开,因为复杂性和缺乏文档,我的用例。简单地说我不能让它正常工作。
You could consider the doorkeeper gem for your API authorization. I considered it but decided against it because of complexity and lacking documentation for my use cases. Put simply I couldn't get it working properly.
有是使用监狱长认证的好文章没有设计出应该给你良好的手感用于认证系统的运动部件。设计是不恰当的API认证,事实上最近制定去掉一件事,可能是API的这是基于令牌的认证有用,显然API的都不是自己的路线图的一部分!
There is a good article on authentication using warden without devise which should give you a good feel for the moving parts of an authentication system. Devise is not appropriate for API authentication and in fact Devise recently removed the one thing that could be useful for API's which was token based authentication, obviously API's are not part of their roadmap!
我用上面提到的文章中的指导,以创建使用一个OAuth 2所有者密码凭证交付式我自己的JSON只有监狱长策略(见的 RFC 6749 )来生成并返回一个承载令牌未来的API请求使用。 API客户端可以轻松地创建JSON做这种认证获得授权访问令牌。
I used the guidance in the article referenced above to create my own JSON only Warden strategy that uses an OAUTH 2 Owner Password Credentials Grant type (See RFC 6749) to generate and return a bearer token for use on future API requests. API clients can easily create the JSON to do this kind of authentication to obtain an authorization access token.
我将提供一些Rails的code的让你开始以下,但你必须融入您的特定环境。没有担保提供:)
I will provide some of the Rails code to get you started below, but you will have to integrate into your specific environment. No warranty offered :)
典狱官初始化:
# config/initializers/warden.rb
Dir["./app/strategies/warden/*.rb"].each { |file| require file }
Rails.application.config.middleware.insert_after ActionDispatch::ParamsParser, Warden::Manager do |manager|
manager.default_strategies :null_auth, :oauth_access_token, :oauth_owner_password
manager.failure_app = UnauthorizedController
end
监狱长战略OAUTH 2密码验证:
Warden strategy for OAUTH 2 password authentication:
# app/strategies/warden/oauth_owner_password_strategy.rb
module Warden
class OauthOwnerPasswordStrategy < Strategies::Base
def valid?
return false if request.get?
params['grant_type'] == 'password' && params['client_id'] == 'web' && ! params['username'].blank?
end
def authenticate!
user = User.with_login(params['username']).first
if user.nil? || user.confirmed_at.nil? || ! user.authenticate!(params['password'])
# delay failures for up to 20ms to thwart timing based attacks
sleep(SecureRandom.random_number(20) / 1000.0)
fail! :message => 'strategies.password.failed'
else
success! user, store: false
end
# ADD HERE: log IP and timestamp of all authentication attempts
end
end
Strategies.add(:oauth_owner_password, OauthOwnerPasswordStrategy)
end
监狱长战略OAUTH 2访问令牌认证方式:
Warden strategy for OAUTH 2 access token authentication:
# app/strategies/warden/oauth_access_token_strategy.rb
module Warden
class OauthAccessTokenStrategy < Strategies::Base
def valid?
# must be a bearer token
return false unless auth_header = request.headers['authorization']
auth_header.split(' ')[0] == 'Bearer'
end
def authenticate!
# Use a periodic cleaner instead
# clean out all old tokens. DOES NOT RUN CALLBACKS!
Token.expired.delete
# lookup bearer token
token = Token.active.first(purpose: 'access', token: request.headers['authorization'].split(' ')[1])
if token && (user = token.user) && user.confirmed_at
success! user, store: false
else
# delay failures for up to 20ms to thwart timing based attacks
sleep(SecureRandom.random_number(20) / 1000.0)
fail! message: 'strategies.oauth_access_token.failed'
end
end
end
Strategies.add(:oauth_access_token, OauthAccessTokenStrategy)
end
空认证策略(可在开发非常有用,只要设置 config.null_auth_user
中的config /环境/ development.rb):
Null authentication strategy (can be useful in development, just set config.null_auth_user
within config/environments/development.rb):
# app/strategies/warden/null_auth_strategy.rb
module Warden
class NullAuthStrategy < Strategies::Base
def valid?
! Rails.configuration.null_auth_user.blank?
end
def authenticate!
user = User.with_login(params["username"]||Rails.configuration.null_auth_user).first
if user.nil?
fail! :message => "strategies.password.failed"
else
success! user, store: false
end
end
end
Strategies.add(:null_auth, NullAuthStrategy)
end
有关JSON客户监狱长故障应用程序(使用了裸金属导轨控制器):
Warden failure application for JSON clients (uses a bare metal rails controller):
# app/controllers/unauthorized_controller.rb
class UnauthorizedController < ActionController::Metal
def self.call(env)
@respond ||= action(:respond)
@respond.call(env)
end
def respond(env)
self.status = 401
self.content_type = 'json'
self.response_body = { 'errors' => ['Authentication failure']}.to_json
end
end
添加以下在你的基地API控制器:
Add the following in your base API controller:
before_filter :authenticate!
protected
helper_method :warden, :signed_in?, :current_user
def warden
request.env['warden']
end
def signed_in?
!current_user.nil?
end
def current_user
@current_user ||= warden.user
end
def authenticate!(*args)
warden.authenticate!(*args)
# ADD ANY POST AUTHENTICATION SETUP CODE HERE
end
一个会话控制器:
class SessionsController < ApiController
skip_before_filter :authenticate!
# TODO exceptions and errors should return unauthorized HTTP response.
# see RFC for details
def create
# mandate the password strategy.
# don't use session store (don't want session cookies on APIs)
authenticate!(scope: :oauth_owner_password, store: false)
if signed_in?
# create access token
token = Token.create! purpose: 'access',
user: current_user,
expires_in: Rails.configuration.session_lifetime
# Ensure response is never cached
response.headers["Cache-Control"] = "no-store"
response.headers["Pragma"] = "no-cache"
response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT"
# send the OAuth response
render json: {
access_token: token.token,
token_type: 'Bearer',
expires_in: token.expires_in,
scope: 'user'
}
end
end
def destroy
Token.current.delete
warden.logout
head :no_content
end
end
您需要定义自己的用户和令牌模型分别跟踪用户和承载令牌,令牌模型需要呼吁一个范围有效
来限制结果集以未到期的令牌。令牌生成应该使用 SecureRandom.urlsafe_base64
You will need to define your own User and Token models for tracking users and bearer tokens respectively, the Token model needs to have a scope called active
to limit the result set to unexpired tokens. Token generation should use SecureRandom.urlsafe_base64
这篇关于用户API认证登录到Web应用程序服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!