2014-11-18 11 views
7

Tôi có ứng dụng Rails chạy trong vùng chứa Docker được gán một ip 172.17.0.3. Yêu cầu đến máy chủ 51.x.x.x được chuyển tiếp đến ứng dụng đường ray trong 172.17.0.3. Cụ thể hơn, điều này đã được thực hiện như vậy:Ứng dụng Rails chuyển tiếp cổng trong Docker dường như gây ra ngoại lệ CSRF

docker run -p 8080:8080 rails_app 

Tuy nhiên, Rails app ném Can't verify CSRF token authenticity lỗi khi người dùng cố gắng truy cập vào một số trang. Nghi ngờ của tôi là Rails nghĩ rằng yêu cầu đến là một cuộc tấn công, vì ip của đích không khớp với ip của ứng dụng Rails - tức là yêu cầu của người dùng được chuyển đến máy chủ 51.x.x.x, trong khi vị trí thực tế của Rails là 172.17.0.3

Có cách nào để tôi nói với Rails rằng các yêu cầu này là hợp pháp không? Là thông tin bổ sung, tôi sử dụng devise để xác thực và unicorn làm máy chủ.

Một số bạn có thể bị cám dỗ đề xuất thay đổi protect_from_forgery with: :exception thành :null_session, nhưng ứng dụng hoạt động tốt khi không được đặt sau proxy. Bên cạnh đó, một số logic sẽ không hoạt động khi tôi thay đổi phần đó vì tôi nghĩ rằng cài đặt sẽ lộn xộn với cách xử lý phiên người dùng.

Đây là cách bố trí của mạng của tôi:

(user from public network) ----> (proxy) ----> (rails app on a private network) 
     (202.x.x.x)   (51.x.x.x)    (172.x.x.x) 

EDIT: Ứng dụng trong development cài đặt. Đây là lỗi tôi nhận được trong các tệp log/development.log.

Started POST "/register" for 202.x.x.x at 2014-11-18 02:27:11 +0000 
Processing by UsersController#create as HTML 
    Parameters: {"utf8"=>"✓", "authenticity_token"=>"aBG3nIAKK1ALMJ1DDYFlMkmqISMBMZc3iLmaeD2byG8=", "user"=>{"email"=>"[email protected]", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}} 
Can't verify CSRF token authenticity 
Completed 422 Unprocessable Entity in 2ms 

ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken): 
    actionpack (4.1.4) lib/action_controller/metal/request_forgery_protection.rb:176:in `handle_unverified_request' 
    actionpack (4.1.4) lib/action_controller/metal/request_forgery_protection.rb:202:in `handle_unverified_request' 
    devise (3.4.0) lib/devise/controllers/helpers.rb:251:in `handle_unverified_request' 
    actionpack (4.1.4) lib/action_controller/metal/request_forgery_protection.rb:197:in `verify_authenticity_token' 
    activesupport (4.1.4) lib/active_support/callbacks.rb:424:in `block in make_lambda' 
    activesupport (4.1.4) lib/active_support/callbacks.rb:160:in `call' 
    activesupport (4.1.4) lib/active_support/callbacks.rb:160:in `block in halting' 
    activesupport (4.1.4) lib/active_support/callbacks.rb:166:in `call' 
    activesupport (4.1.4) lib/active_support/callbacks.rb:166:in `block in halting' 
    activesupport (4.1.4) lib/active_support/callbacks.rb:149:in `call' 
    activesupport (4.1.4) lib/active_support/callbacks.rb:149:in `block in halting_and_conditional' 
    activesupport (4.1.4) lib/active_support/callbacks.rb:149:in `call' 
    activesupport (4.1.4) lib/active_support/callbacks.rb:149:in `block in halting_and_conditional' 
activesupport (4.1.4) lib/active_support/callbacks.rb:86:in `run_callbacks' 
    actionpack (4.1.4) lib/abstract_controller/callbacks.rb:19:in `process_action' 
    actionpack (4.1.4) lib/action_controller/metal/rescue.rb:29:in `process_action' 
    actionpack (4.1.4) lib/action_controller/metal/instrumentation.rb:31:in `block in process_action' 
    activesupport (4.1.4) lib/active_support/notifications.rb:159:in `block in instrument' 
    activesupport (4.1.4) lib/active_support/notifications/instrumenter.rb:20:in `instrument' 
    activesupport (4.1.4) lib/active_support/notifications.rb:159:in `instrument' 
    actionpack (4.1.4) lib/action_controller/metal/instrumentation.rb:30:in `process_action' 
    actionpack (4.1.4) lib/action_controller/metal/params_wrapper.rb:250:in `process_action' 
    activerecord (4.1.4) lib/active_record/railties/controller_runtime.rb:18:in `process_action' 
    actionpack (4.1.4) lib/abstract_controller/base.rb:136:in `process' 
    actionview (4.1.4) lib/action_view/rendering.rb:30:in `process' 
    actionpack (4.1.4) lib/action_controller/metal.rb:196:in `dispatch' 
    actionpack (4.1.4) lib/action_controller/metal/rack_delegation.rb:13:in `dispatch' 
    actionpack (4.1.4) lib/action_controller/metal.rb:232:in `block in action' 
    actionpack (4.1.4) lib/action_dispatch/routing/route_set.rb:82:in `call' 
    actionpack (4.1.4) lib/action_dispatch/routing/route_set.rb:82:in `dispatch' 
    actionpack (4.1.4) lib/action_dispatch/routing/route_set.rb:50:in `call' 
    actionpack (4.1.4) lib/action_dispatch/routing/mapper.rb:45:in `call' 
    actionpack (4.1.4) lib/action_dispatch/journey/router.rb:71:in `block in call' 
    actionpack (4.1.4) lib/action_dispatch/journey/router.rb:59:in `each' 
    actionpack (4.1.4) lib/action_dispatch/journey/router.rb:59:in `call' 
    actionpack (4.1.4) lib/action_dispatch/routing/route_set.rb:678:in `call' 
    omniauth (1.2.2) lib/omniauth/strategy.rb:186:in `call!' 
    omniauth (1.2.2) lib/omniauth/strategy.rb:164:in `call' 
    omniauth (1.2.2) lib/omniauth/strategy.rb:186:in `call!' 
    omniauth (1.2.2) lib/omniauth/strategy.rb:164:in `call' 
    omniauth (1.2.2) lib/omniauth/strategy.rb:186:in `call!' 
    omniauth (1.2.2) lib/omniauth/strategy.rb:164:in `call' 
    omniauth (1.2.2) lib/omniauth/strategy.rb:186:in `call!' 
    omniauth (1.2.2) lib/omniauth/strategy.rb:164:in `call' 
    omniauth (1.2.2) lib/omniauth/strategy.rb:186:in `call!' 
    omniauth (1.2.2) lib/omniauth/strategy.rb:164:in `call' 
    warden (1.2.3) lib/warden/manager.rb:35:in `block in call' 
    warden (1.2.3) lib/warden/manager.rb:34:in `catch' 
    warden (1.2.3) lib/warden/manager.rb:34:in `call' 
    rack (1.5.2) lib/rack/etag.rb:23:in `call' 
    rack (1.5.2) lib/rack/conditionalget.rb:35:in `call' 
    rack (1.5.2) lib/rack/head.rb:11:in `call' 
    actionpack (4.1.4) lib/action_dispatch/middleware/params_parser.rb:27:in `call' 
    actionpack (4.1.4) lib/action_dispatch/middleware/flash.rb:254:in `call' 
    rack (1.5.2) lib/rack/session/abstract/id.rb:225:in `context' 
    rack (1.5.2) lib/rack/session/abstract/id.rb:220:in `call' 
    actionpack (4.1.4) lib/action_dispatch/middleware/cookies.rb:560:in `call' 
    activerecord (4.1.4) lib/active_record/query_cache.rb:36:in `call' 
    activerecord (4.1.4) lib/active_record/connection_adapters/abstract/connection_pool.rb:621:in `call' 
    activerecord (4.1.4) lib/active_record/migration.rb:380:in `call' 
    actionpack (4.1.4) lib/action_dispatch/middleware/callbacks.rb:29:in `block in call' 
    activesupport (4.1.4) lib/active_support/callbacks.rb:82:in `run_callbacks' 
    actionpack (4.1.4) lib/action_dispatch/middleware/callbacks.rb:27:in `call' 
    actionpack (4.1.4) lib/action_dispatch/middleware/reloader.rb:73:in `call' 
    actionpack (4.1.4) lib/action_dispatch/middleware/remote_ip.rb:76:in `call' 
    actionpack (4.1.4) lib/action_dispatch/middleware/debug_exceptions.rb:17:in `call' 
    actionpack (4.1.4) lib/action_dispatch/middleware/show_exceptions.rb:30:in `call' 
    railties (4.1.4) lib/rails/rack/logger.rb:38:in `call_app' 
    railties (4.1.4) lib/rails/rack/logger.rb:20:in `block in call' 
    activesupport (4.1.4) lib/active_support/tagged_logging.rb:68:in `block in tagged' 
    activesupport (4.1.4) lib/active_support/tagged_logging.rb:26:in `tagged' 
    activesupport (4.1.4) lib/active_support/tagged_logging.rb:68:in `tagged' 
    railties (4.1.4) lib/rails/rack/logger.rb:20:in `call' 
    actionpack (4.1.4) lib/action_dispatch/middleware/request_id.rb:21:in `call' 
    rack (1.5.2) lib/rack/methodoverride.rb:21:in `call' 
    rack (1.5.2) lib/rack/runtime.rb:17:in `call' 
    activesupport (4.1.4) lib/active_support/cache/strategy/local_cache_middleware.rb:26:in `call' 
    rack (1.5.2) lib/rack/lock.rb:17:in `call' 
    actionpack (4.1.4) lib/action_dispatch/middleware/static.rb:64:in `call' 
    rack-cors (0.2.9) lib/rack/cors.rb:54:in `call' 
    rack (1.5.2) lib/rack/sendfile.rb:112:in `call' 
    railties (4.1.4) lib/rails/engine.rb:514:in `call' 
    railties (4.1.4) lib/rails/application.rb:144:in `call' 
    rack (1.5.2) lib/rack/lint.rb:49:in `_call' 
    rack (1.5.2) lib/rack/lint.rb:37:in `call' 
    rack (1.5.2) lib/rack/showexceptions.rb:24:in `call' 
    rack (1.5.2) lib/rack/commonlogger.rb:33:in `call' 
    sinatra (1.4.5) lib/sinatra/base.rb:217:in `call' 
    rack (1.5.2) lib/rack/chunked.rb:43:in `call' 
    rack (1.5.2) lib/rack/content_length.rb:14:in `call' 
    unicorn (4.8.3) lib/unicorn/http_server.rb:576:in `process_client' 
    unicorn (4.8.3) lib/unicorn/http_server.rb:670:in `worker_loop' 
    unicorn (4.8.3) lib/unicorn/http_server.rb:525:in `spawn_missing_workers' 
    unicorn (4.8.3) lib/unicorn/http_server.rb:140:in `start' 
    unicorn (4.8.3) bin/unicorn:126:in `<top (required)>' 
+0

Bạn đã bao giờ tìm ra điều này chưa? Tôi vừa xây dựng một môi trường sản xuất trên một máy ảo ubuntu bằng cách sử dụng các thùng chứa docker ... bình, mysql, nginx và uwsgi. Tôi cũng nhận được lỗi mã thông báo CRSF trên biểu mẫu. – Chockomonkey

+0

Chỉ cần tìm một thứ gì đó tương tự ... Nếu bạn đã xác định SERVER_NAME trong cấu hình của mình, hãy thử xóa nó. – Chockomonkey

+0

@Chockomonkey Bạn có thể mở rộng ý nghĩa của mình không? Bạn có nghĩa là nếu bạn có 'SERVER_NAME' được định nghĩa là một biến môi trường? –

Trả lời

1

Từ việc đọc lướt qua của 'protect_from_forgery method', chúng ta thấy như sau:

def protect_from_forgery(options = {}) 
    self.forgery_protection_strategy = protection_method_class(options[:with] || :null_session) 
    self.request_forgery_protection_token ||= :authenticity_token 
    prepend_before_action :verify_authenticity_token, options 
    append_after_action :verify_same_origin_request 
    end 

nào có trước khi hành động gọi lại gọi là 'verify_authenticity_token'. Nếu chúng tôi xem xét nguồn của chúng tôi, chúng tôi tìm thấy những điều sau:

def verify_authenticity_token 
    mark_for_same_origin_verification! 

    if !verified_request? 
     logger.warn "Can't verify CSRF token authenticity" if logger 
     handle_unverified_request 
    end 
    end 

Từ đó chúng tôi lưu ý rằng nó gọi 'verified_request?'.

def verified_request? 
    !protect_against_forgery? || request.get? || request.head? || 
     form_authenticity_token == params[request_forgery_protection_token] || 
     form_authenticity_token == request.headers['X-CSRF-Token'] 
    end 

Do bản chất của ngoại lệ được nêu ra, tôi nghĩ rằng một hoặc nhiều điều kiện đó không được đáp ứng. Tôi không nghĩ rằng nó có liên quan đến địa chỉ IP.

0

Nếu ứng dụng đường ray của bạn đang nói qua không phải SSL cho proxy của bạn, có thể có vấn đề trong đó ActiveRecord :: SessionStore của bạn sẽ phù hợp với trường hợp đó.

sửa chữa của chúng tôi là làm cho các cửa hàng phiên không an toàn:

OurApplication::Application.config.session_store :active_record_store, secure: false

Edit: Vẫn không có sửa chữa chưa ... Chúng tôi có thể sẽ phải làm cho SSL chấm dứt ở các ứng dụng như trái ngược với proxy trên này.

Vì vậy, đối với chúng tôi, vấn đề không liên quan gì đến SSL cuối cùng. Chúng tôi đã thực hiện cuộc gọi javascript trên trang tải đầu tiên đang cố bắt tay vào dịch vụ phụ trợ (qua POST), nhưng chúng tôi đã không định cấu hình đúng cách HAProxy để định tuyến cuộc gọi đến dịch vụ đó, thay vào đó POST đánh Rails.Mặc dù Rails đã trả lại 404 cho tuyến đường, nhưng nó cũng đặt lại phiên vì mã thông báo CSRF bị thiếu trong yêu cầu. Sửa lỗi định tuyến của HAProxy đã khắc phục được sự cố.

Kịch bản của chúng tôi hầu như không liên quan gì đến bạn và trong Rails 4, họ đã thực hiện hành vi mặc định là protect_from_forgery để tăng ngoại lệ thay vì đặt lại phiên. Ồ, và cuối cùng chúng tôi cũng cần phải đặt cửa hàng phiên thành không an toàn:

OurApplication::Application.config.session_store :active_record_store, secure: false

Các vấn đề liên quan