programing

이 Rails JSON 인증 API(Gand 사용)는 안전한가요?

goodjava 2023. 3. 26. 11:20

이 Rails JSON 인증 API(Gand 사용)는 안전한가요?

My Rails 앱은 인증에 Gand를 사용합니다.자매 iOS 앱이 있으며 사용자는 웹 앱에서 사용하는 것과 동일한 자격 증명을 사용하여 iOS 앱에 로그인할 수 있습니다.그래서 인증을 위해서는 API가 필요합니다.

이 튜토리얼에는 비슷한 질문들이 많이 있습니다만, 이 튜토리얼은 구식인 것 같습니다.token_authenticatable그 후 모듈이 Gand에서 삭제되어 일부 행이 에러를 던지고 있습니다.(는 Gand 3.2.2를 사용하고 있습니다.) 그 튜토리얼을 바탕으로 직접 롤링을 시도했지만 100% 자신이 없습니다.뭔가 잘못 이해했거나 놓친 것 같습니다.

먼저, 이 요지의 조언에 따라, 나는 다음과 같이 덧붙였습니다.authentication_token내 텍스트 속성users 표와 을 참조해 주십시오.user.rb:

before_save :ensure_authentication_token

def ensure_authentication_token
  if authentication_token.blank?
    self.authentication_token = generate_authentication_token
  end
end

private

  def generate_authentication_token
    loop do
      token = Devise.friendly_token
      break token unless User.find_by(authentication_token: token)
    end
  end

다음으로 다음 컨트롤러가 있습니다.

api_controller.syslog

class ApiController < ApplicationController
  respond_to :json
  skip_before_filter :authenticate_user!

  protected

  def user_params
    params[:user].permit(:email, :password, :password_confirmation)
  end
end

(주)에 해 주세요.application_controllerbefore_filter :authenticate_user!

api/syslog_controller.displuss

class Api::SessionsController < Devise::RegistrationsController
  prepend_before_filter :require_no_authentication, :only => [:create ]

  before_filter :ensure_params_exist

  respond_to :json

  skip_before_filter :verify_authenticity_token

  def create
    build_resource
    resource = User.find_for_database_authentication(
      email: params[:user][:email]
    )
    return invalid_login_attempt unless resource

    if resource.valid_password?(params[:user][:password])
      sign_in("user", resource)
      render json: {
        success: true,
        auth_token: resource.authentication_token,
        email: resource.email
      }
      return
    end
    invalid_login_attempt
  end

  def destroy
    sign_out(resource_name)
  end

  protected

    def ensure_params_exist
      return unless params[:user].blank?
      render json: {
        success: false,
        message: "missing user parameter"
      }, status: 422
    end

    def invalid_login_attempt
      warden.custom_failure!
      render json: {
        success: false,
        message: "Error with your login or password"
      }, status: 401
    end
end

api/registrations_controller.displays.

class Api::RegistrationsController < ApiController
  skip_before_filter :verify_authenticity_token

  def create
    user = User.new(user_params)
    if user.save
      render(
        json: Jbuilder.encode do |j|
          j.success true
          j.email user.email
          j.auth_token user.authentication_token
        end,
        status: 201
      )
      return
    else
      warden.custom_failure!
      render json: user.errors, status: 422
    end
  end
end

또한 config/routes.rb:

  namespace :api, defaults: { format: "json" } do
    devise_for :users
  end

나는 조금 내 능력 밖이고 여기에 내 미래의 자신이 돌아보고 움츠러들 무언가가 있다고 확신한다.일부 부품:

우선, 당신은 그것을 알아차릴 것이다.Api::SessionsController 계승하다Devise::RegistrationsController, 「」입니다.Api::RegistrationsController 계승하다ApiController 밖에도 (조종사가 있다)와 .Api::EventsController < ApiController다른 모델에서는 표준 REST를 취급하고 있으며, Gand와는 별로 접촉하고 있지 않습니다.)은 꽤 흉한 배열이지만, 을 찾을 수 수 없었습니다.Api::RegistrationsController위에 링크된 튜토리얼에는 라인이 있습니다.include Devise::Controllers::InternalHelpers단, 이 모듈은 Gand의 최신 버전에서 삭제된 것으로 보입니다.

둘째, 회선을 사용하여 CSRF 보호를 비활성화했습니다.skip_before_filter :verify_authentication_tokenJSON API가 CSRF 공격에 취약한지에 대해 모순되거나 이해하기 어려운 조언을 많이 듣습니다만, 그 라인을 추가하는 것만이 제가 이 일을 할 수 있는 유일한 방법입니다.

셋째, 사용자가 로그인한 후 인증이 어떻게 이루어지는지 알고 싶습니다.API 호출이 있다고 가정합니다.GET /api/friends이치노iOS를 있습니다.authentication_token을 하지 각를 들어, 「변경을 하지 않는 사용자」라고 하는 것입니다.에서 모든 요청과 함께 매개 변수로 제출합니다.GET /api/friends?authentication_token=abcdefgh1234그에 나의 , , , , , 「」Api::FriendsControllerUser.find_by(authentication_token: params[:authentication_token])current_user를 .이게 정말 이렇게 간단한 건가요, 아니면 제가 뭘 놓치고 있는 건가요?

이 매머드 질문을 끝까지 읽어주신 모든 분들께 시간을 내주셔서 감사합니다!요약:

  1. 이 로그인 시스템은 안전한가요?아니면 CSRF 공격에 대해 간과하거나 오해한 부분이 있습니까?
  2. 사용자가 로그인한 후 요청을 인증하는 방법에 대한 이해는 올바릅니까?('세 번째' 참조)." " " " 。
  3. 이 코드를 정리하거나 더 좋게 만들 수 있는 방법이 없을까요?특히 컨트롤러 1개를 상속받는 추악한 설계Devise::RegistrationsController ★★★★★★★★★★★★★★★★ApiController.

감사합니다!

CSRF를 무효로 하고 싶지 않은 것은, JSON API에 적용되지 않는다고 하는 것은 알고 있습니다만, 이것은 오해입니다.이 설정을 유효하게 하려면 , 다음의 몇개의 변경을 실시합니다.

  • 서버 측에서 세션컨트롤러에 after_filter를 추가합니다.

    after_filter :set_csrf_header, only: [:new, :create]
    
    protected
    
    def set_csrf_header
       response.headers['X-CSRF-Token'] = form_authenticity_token
    end
    

    그러면 토큰이 생성되어 세션에 저장되고 선택한 액션에 대한 응답 헤더에 토큰이 복사됩니다.

  • 클라이언트측(iOS)에서는, 2개의 것이 갖추어져 있는 것을 확인할 필요가 있습니다.

    • 클라이언트는 이 헤더의 모든 서버 응답을 스캔하여 헤더가 전달될 때 보관해야 합니다.

      ... get ahold of response object
      // response may be a NSURLResponse object, so convert:
      NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
      // grab token if present, make sure you have a config object to store it in
      NSString *token = [[httpResponse allHeaderFields] objectForKey:@"X-CSRF-Token"];
      if (token)
         [yourConfig setCsrfToken:token];
      
    • 마지막으로 클라이언트는 송신하는 모든 '비 GET' 요구에 이 토큰을 추가해야 합니다.

      ... get ahold of your request object
      if (yourConfig.csrfToken && ![request.httpMethod isEqualToString:@"GET"])
        [request setValue:yourConfig.csrfToken forHTTPHeaderField:@"X-CSRF-Token"];
      

이 퍼즐의 마지막 조각은 고안하기 위해 로그인할 때 두 개의 후속 세션/csrf 토큰이 사용되고 있음을 이해하는 것입니다.로그인 흐름은 다음과 같습니다.

GET /users/sign_in ->
  // new action is called, initial token is set
  // now send login form on callback:
  POST /users/sign_in <username, password> ->
    // create action called, token is reset
    // when login is successful, session and token are replaced 
    // and you can send authenticated requests

이 예는 Gandblog - https://gist.github.com/josevalim/fb706b1e933ef01e4fb6의 코드를 모방한 것 같습니다.

이 투고에서 설명한 바와 같이, 안전하지 않은 옵션이라고 하는 옵션 1과 같은 작업을 하고 있습니다.중요한 것은 사용자가 저장될 때마다 단순히 인증 토큰을 리셋하지 않는 것입니다.토큰은 (API의 Token Controller에 의해) 명시적으로 생성되어야 하며 정기적으로 만료되어야 한다고 생각합니다.

(제가 아는 한) 아무도 이것에 대해 더 이상의 정보를 가지고 있지 않기 때문에 '내 생각'이라고 말하는 것을 알 수 있을 것이다.

웹 어플리케이션에서 가장 일반적인 취약성 상위10은 OWASP Top 10에 기재되어 있습니다.이 질문에서는 Cross-Site Request Formature(CSRF; 사이트 간 요구 위조) 보호가 디세블로 되어 있어 CSRF가 OWASDP Top 10에 포함되어 있는 것을 나타내고 있습니다.즉, CSRF는 공격자가 인증된 사용자로서 액션을 수행하기 위해 사용합니다.CSRF 보호를 디세블로 하면, 애플리케이션의 리스크가 높은 취약성이 발생해, 시큐어한 인증 시스템을 갖추는 목적이 저하됩니다.클라이언트가 CSRF 동기 토큰을 전달하지 못했기 때문에 CSRF 보호가 실패했을 가능성이 있습니다.

OWASP Top 10을 모두 읽어보십시오. 그렇게 하지 않으면 매우 위험합니다.Breaked Authentication and Session Management(인증 및 세션 관리)에 주의하고 세션 관리 치트 시트도 확인하십시오.

언급URL : https://stackoverflow.com/questions/20745843/is-this-rails-json-authentication-api-using-devise-secure