2014-09-17 2 views
25

일반 old Ruby 객체 (PORO)를 사용하여 컨트롤러에서 추상화 논리를 추출하는 응용 프로그램을 작성하고 있습니다.레일즈에 "허가되지 않은"예외가 있습니까?

현재, 나는 컨트롤러 수준에서 I rescue_fromNotAuthorized라는 사용자 정의 예외 클래스를 가지고,하지만 난 알고 궁금 해서요 : 합니까 레일 (4)는 이미 작업이 허가되지 않았 음을 나타 내기 위해 예외와 ​​함께?이 예외를 구현하여 바퀴를 재발 명하고 있습니까?

명확화 : raise AuthorizationException은 컨트롤러 내부 어디에서도 발생하지 않으며 컨트롤러 외부의 완전히 분리 된 PORO 내부에서 발생합니다. 객체에는 HTTP, 라우트 또는 컨트롤러에 대한 지식이 없습니다.

+0

http 오류 코드 401은 권한이 없다는 것을 의미하며, 401 상태 코드를 반환하도록 레일스에 알리고 원하는 모든보기를 렌더링합니다. –

+1

@MohammadAbuShady - 저는 그가 ActionController :: RoutingError.new (' 찾을 수 없음 ')'을 선택하면 응급 statmenets없이 응용 프로그램을 자동으로 렌더링합니다 (404). – BroiSatse

+2

나는 대개 단지 devise + cancan을 사용합니다. 인증 및 권한 부여를위한 좋은 조합입니다. –

답변

22

레일즈는 예외를 :unauthorized으로 매핑하지 않습니다.

@@rescue_responses.merge!(
    'ActionController::RoutingError'    => :not_found, 
    'AbstractController::ActionNotFound'   => :not_found, 
    'ActionController::MethodNotAllowed'   => :method_not_allowed, 
    'ActionController::UnknownHttpMethod'  => :method_not_allowed, 
    'ActionController::NotImplemented'   => :not_implemented, 
    'ActionController::UnknownFormat'   => :not_acceptable, 
    'ActionController::InvalidAuthenticityToken' => :unprocessable_entity, 
    'ActionDispatch::ParamsParser::ParseError' => :bad_request, 
    'ActionController::BadRequest'    => :bad_request, 
    'ActionController::ParameterMissing'   => :bad_request 
) 

당신은 응용 프로그램의 구성에서 사용자 정의 예외에서 추가 할 수 있습니다 (또는 사용자 정의 Railtie) :

config.action_dispatch.rescue_responses.merge!(
    'ActiveRecord::RecordNotFound' => :not_found, 
    'ActiveRecord::StaleObjectError' => :conflict, 
    'ActiveRecord::RecordInvalid' => :unprocessable_entity, 
    'ActiveRecord::RecordNotSaved' => :unprocessable_entity 
) 

actionpack/lib/action_dispatch/middleware/exception_wrapper.rb을 :

기본 매핑

activerecord/lib/active_record/railtie.rb에 정의되어

Your::Application.configure do 

    config.action_dispatch.rescue_responses.merge!(
    'AuthorizationException' => :unauthorized 
) 

    # ... 

end 

또는 단순히 rescue_from을 사용하십시오.

+1

내 질문에 답해 주셔서 감사합니다. 예외가 Mongoid와 ORM으로 매핑되는 방식이 궁금합니다. – Rick

+2

@Rick https://github.com/mongoid/mongoid/blob/master/lib/mongoid/railtie.rb#L37 – Stefan

+1

@ Stefan의 링크는 시간이 지남에 따라 변하는 'master'의 특정 줄 번호를 참조합니다. 다음은 해당 코드에 대한 "퍼마"링크입니다. https://github.com/mongoid/mongoid/blob/v4.0.2/lib/mongoid/railtie.rb#L24 –

13

레일즈가이 예외를 도입하지 않은 이유는 권한 부여 및 인증이 레일스 고유의 동작 (물론 기본 인증을 고려하지 않음)이 아니기 때문이라고 생각합니다.

일반적으로 이들은 다른 라이브러리의 책임입니다. Devise for NotAuthenticated; Pundit는 CanCanCan는 NotAuthorized에 대한 Rollify)는 실제로 같은 나는

이 그래서 방법 나는 보통이 문제를 달려 드는 방법이다

책임)입니다 아니라고 말했다 있기 때문에 (ActionController::NotAuthorized 같은 사용자 정의 예외 ActionController을 확장하는 나쁜 일이 될 수 있습니다 주장 나는 그러므로 내 컨트롤러에서 나는이 명확하게 정의

class MyStuff < ApplicationController 
    def index 
    if current_user.admin? 
     # .... 
    else 
     raise ApplicationController::NotAuthorized 
    end 
    end 
end 

을 할 수 ApplicationController

class ApplicationController < ActionController::Base 
    NotAuthorized = Class.new(StandardError) 
    # ...or if you really want it to be ActionController 
    # NotAuthorized = Class.new(ActionController::RoutingError) 

    rescue_from ActiveRecord::RecordNotFound do |exception| 
    render_error_page(status: 404, text: 'Not found') 
    end 

    rescue_from ApplicationController::NotAuthorized do |exception| 
    render_error_page(status: 403, text: 'Forbidden') 
    end 

    private 

    def render_error_page(status:, text:, template: 'errors/routing') 
    respond_to do |format| 
     format.json { render json: {errors: [message: "#{status} #{text}"]}, status: status } 
     format.html { render template: template, status: status, layout: false } 
     format.any { head status } 
    end 
    end 
end 

에서 사용자 정의 예외를 도입했습니다 레이어 당신의 애 썼는데 그 이 예외를 발생 시켜서 잡아내는 것은 제 3 자 lib가 아닌 응용 프로그램 계층입니다.

제 3 자 lib 클래스에서 예외를 정의하고 응용 프로그램 계층에서 구조를 변경하면 라이브러리가 변경 될 수 있습니다 (예, 레일을 의미 함). 예외 클래스 변경의 의미가 브레이크를 걸는 것처럼 실제적으로 위험합니다 rescue_from

사람들이 많이있는 레일을 raise - rescue_from (현재 일부 전문가들 사이에서 안티 패턴을 고려하고 있음) 인 많은 기사를 읽을 수 있으며 특정 확장은 사실이지만 당신이 입는 예외 완전히 통제 할 수 없어!

즉 제 3 자 예외 (특정 지점에 대한 Devise 및 Rails 포함)를 의미합니다. 응용 프로그램에서 예외 클래스를 정의하면 타사 lib에서 중계하지 않습니다. => 전체 제어 => 사용자는 rescue_from을 사용할 수 있습니다.