用户API认证登录到Web应用程序服务器 [英] API Authentication for user logged in to a Web App server

查看:146
本文介绍了用户API认证登录到Web应用程序服务器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我建立一个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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆