복붙노트

[RUBY-ON-RAILS] API 인증은 사용자의 웹 응용 프로그램 서버에 로그인

RUBY-ON-RAILS

API 인증은 사용자의 웹 응용 프로그램 서버에 로그인

나는 웹 응용 프로그램과 별도의 API를 구축하고 (그래서 그들은 원하는 경우 사용자가 사람과 함께 수집 된 데이터를 공유 할 수 있습니다) 루비 온 레일즈를 사용하여. 사용자가 API 서버에 게시해야 웹 응용 프로그램 및 채우기 데이터에 로그인 할 수 있습니다.

내가 지금까지 읽은 모든에서, 나는 사용자가 웹 응용 프로그램에 로그인되어 있는지 여부를 확인하기 위해 쿠키 기반 인증을 사용할 수있는 것 같아요. 이제하자 사용자가 API 서버에 데이터를 게시하고자하는 것을 말한다. 사용자가 웹 응용 프로그램 서버에 인증되어 있기 때문에, 어떻게 포스트 요청은 API가이 로그인 한 특정 사용자의 데이터를지고 있음을 알 수 있도록해야한다. 사용자가 API가 데이터를하고 싶어 또한 경우 그에게 개인은 / 그녀는 어떻게 GET 요청은 이러한 목적으로해야한다입니까?

해결법

  1. ==============================

    1.당신은 당신의 API 인증을위한 문지기 보석을 고려할 수 있습니다. 나는 그것을 생각하지만 때문에 복잡 내 사용 사례에 대한 설명서를 부족에 대해 결정했다. 넣어 단순히 내가 제대로 작동을 가져올 수 없습니다.

    당신은 당신의 API 인증을위한 문지기 보석을 고려할 수 있습니다. 나는 그것을 생각하지만 때문에 복잡 내 사용 사례에 대한 설명서를 부족에 대해 결정했다. 넣어 단순히 내가 제대로 작동을 가져올 수 없습니다.

    인증 시스템의 움직이는 부분에 대해 당신에게 좋은 느낌을 주어야한다 유증없이 소장 사용하여 인증에 대한 좋은 기사가있다. 유증은 유증 API 인증 사실 적합하지 않다가 최근에 분명히 API의의가 로드맵의 일부가 아닌, 기반 인증 토큰 된 API 년대에 유용 할 수있는 한 가지를 제거!

    내가 사용하는 OAUTH이 소유자 암호 자격 증명을 부여 유형 (참조 RFC 6749)을 생성하고 향후 API 요청에서 사용하기 위해 토큰 베어러를 반환 할 만 소장 전략을 내 자신의 JSON을 만들 수 위의 참조 문서의 지침을 사용했다. API 클라이언트는 쉽게 인증 액세스 토큰을 얻기 위해 이러한 종류의 인증을 수행 할 JSON을 만들 수 있습니다.

    난 당신이 아래에 시작하는 레일 코드의 일부를 제공 할 것입니다,하지만 당신은 사용자의 특정 환경에 통합해야합니다. 아니 보증은 제공하지 않습니다 :)

    초기화 소장 :

    # 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 암호 인증에 대한 소장 전략 :

    # 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이 액세스 토큰 인증에 대한 소장 전략 :

    # 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
    

    널 인증 전략 (설정 / 환경 / development.rb 내에서 단지 세트 config.null_auth_user, 개발에 유용 할 수 있습니다)

    # 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 클라이언트 소장 실패 애플리케이션 (베어 메탈 제어기 레일 사용) :

    # 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 컨트롤러에 다음을 추가합니다 :

    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를 사용해야합니다

  2. ==============================

    2.당신은 웹 애플리케이션 서버와 서로 웹 응용 프로그램 서버의 사용자에서 업데이트가있을 때마다 이야기 할 필요가있는 별도의 API 서버를 말할 때. 모든 나는 레일 엔진으로 3 엔티티로 분해를 제안 할 수 있습니다.

    당신은 웹 애플리케이션 서버와 서로 웹 응용 프로그램 서버의 사용자에서 업데이트가있을 때마다 이야기 할 필요가있는 별도의 API 서버를 말할 때. 모든 나는 레일 엔진으로 3 엔티티로 분해를 제안 할 수 있습니다.

    왜 코어? 코어 엔진 : 당신이 당신의 비즈니스 로직을 업데이트해야 할 때, 때문에, 하나의 장소가 될 것입니다.

    이제 웹 응용 프로그램 서버에서 API 호출을 인증에 더 귀하의 질문에 대답합니다. 당신은 필요 :

    당신이 API를 고정으로 완료되면, 당신은 당신의 웹 응용 프로그램의 인증 로직을 구현할 수 있습니다. 당신은 API에서 응용 프로그램을 인증하는 OAuth2를 사용할 수 있습니다.

    또한, 단지의 OAuth로 API를 사용할 수 있도록하는 문지기를 사용하여 호출 https://doorkeeper-provider.herokuapp.com/#client-applications

    P.S : 내가하는 API에서 JSON 응답을 선호, 그것은 내가 말하고 싶지만 선호하는 추세입니다. ;)

    편집 - 우편 배달부는 응용 프로그램에 대한 당신이 실제로 쓰기 전에 실험 / 가짜 API를 만들기위한 크롬 확장 기능입니다. 그것은 당신이 마지막으로 하루의 끝에 설계가 무엇인지 것 때문에 훨씬 더 빠릅니다.

  3. ==============================

    3.보통은 다음과 같이 작동합니다. 앱의 문제를 모든 사용자에 대해 토큰 비밀은 (그것이 길어, 예를 들어 MD5 해시 될 수 있으며, 그것은 아주 무작위이다). 토큰은 사용자가 안전하게 보관해야합니다. 당신은 두 가지 규칙에 따라이 작업을 수행 할 수 있습니다 : - 공개적으로 토큰을 공개하지 (모든 요청은 백엔드에서해야한다, 더 AJAX 등 호출 없음) - 그들은 암호화되도록 모든 요청, HTTPS를 통해해야한다

    보통은 다음과 같이 작동합니다. 앱의 문제를 모든 사용자에 대해 토큰 비밀은 (그것이 길어, 예를 들어 MD5 해시 될 수 있으며, 그것은 아주 무작위이다). 토큰은 사용자가 안전하게 보관해야합니다. 당신은 두 가지 규칙에 따라이 작업을 수행 할 수 있습니다 : - 공개적으로 토큰을 공개하지 (모든 요청은 백엔드에서해야한다, 더 AJAX 등 호출 없음) - 그들은 암호화되도록 모든 요청, HTTPS를 통해해야한다

    이유 대신 사용자 이름 및 암호의 토큰을 사용 하는가? 경우 손상되어 토큰 당신은 그것을 취소 할 수 있으며 계정을 통해 사용자는 여전히 제어 할 수 있습니다. 또한, 계정에 관련된 이메일 변경 또는 비밀번호와 같은 토큰 기반 인증 동작에 특정되지 않을 것이다.

    토큰은 API 짓을 각 요청과 함께 PARAM로 전달되어야한다.

  4. ==============================

    4.당신은 JSON, XML 기반의 API를 사용 rabl 보석 https://github.com/nesquena/rabl를 구축합니다.

    당신은 JSON, XML 기반의 API를 사용 rabl 보석 https://github.com/nesquena/rabl를 구축합니다.

    간단한 인증을 위해 제어기에 세션 변수 구비 레일 세션 기반 인증 간다. 당신이 깔끔한 원하는 경우, 사용자에 대한 몇 가지 기능은 다음 authologic 보석 https://github.com/binarylogic/authlogic에 대한 이동합니다.

    당신이 완전한 사용자 관리를 원한다면, 유증 보석에 대한 이동합니다.

  5. ==============================

    5.사용자의 쿠키에 저장되어있는 사용자의 상태를 추적하는 데 사용하는 세션을 레일.

    사용자의 쿠키에 저장되어있는 사용자의 상태를 추적하는 데 사용하는 세션을 레일.

    세션에 대한 문서는 여기에서 찾을 수 있습니다

    당신이 그런 고안 같은 인증 시스템을 활용할 경우에, 당신은 당신의 컨트롤러에 CURRENT_USER 방법뿐만 아니라 사용자의 특정 요구에 따라 활용할 수있는 다양한 도우미의 톤에 액세스 할 수 있습니다

  6. from https://stackoverflow.com/questions/20689759/api-authentication-for-user-logged-in-to-a-web-app-server by cc-by-sa and MIT license