2011-07-07 26 views
12

Tôi đang sử dụng Rails 3.1.0.rc4 và tôi đang làm việc để thực hiện các kiểm tra tích hợp với DSL mới giống như của Capybara và Rspec (sử dụng xác thực Devise)Đường ray - Mất phiên với Kiểm tra tích hợp và Capybara - CSRF có liên quan?

Vấn đề tôi gặp phải là khi tôi chạy một thử nghiệm tích hợp, trình điều khiển rack-test từ capybara dường như chỉ mất hoàn toàn phiên đăng nhập của người dùng, trên thực tế, phiên dường như chỉ rõ ràng hoàn toàn.

Sau những ngày gỡ lỗi, tôi hoàn toàn mất đi lý do tại sao. Sắp xếp từng dòng thông qua ngăn xếp phần mềm trung gian, tôi tin rằng tôi đã loại trừ sự cố xảy ra trong một số ActiveRecord::SessionStore đang gây ra vấn đề này. Tôi đã đọc here rằng Rails sẽ xóa một phiên nếu nó không thể xác thực mã thông báo CSRF, điều này khiến tôi tin rằng tôi đã có cấu hình sai và vì lý do nào đó, kiểm tra này không xác thực mã thông báo CSRF chính xác .

Đây là những gì có trong session_store.rb tôi trong thư mục/initializers:

MyApp::Application.config.session_store :active_record_store 

Có ai người hiểu biết về bảo vệ CSRF trong đường ray có bất kỳ dẫn trên tại sao điều này có thể xảy ra?

Ngoài ra, đây là một số điều cần lưu ý:

  • điều tôi đang cố gắng để kiểm tra thực sự hoạt động trong trình duyệt riêng của mình, chỉ có một bài kiểm tra này bị giảm phiên
  • phiên dường như để có được giảm sau khi gửi biểu mẫu mà url hành động đến một máy chủ khác. Tôi đang sử dụng đá quý VCR để nắm bắt các yêu cầu/phản hồi cho máy chủ bên ngoài này trong thử nghiệm và trong khi tôi tin rằng tôi đã loại trừ yêu cầu bên ngoài là vấn đề, điều này có thể có liên quan trực tiếp đến mã thông báo CSRF không xác thực, do đó xóa phiên.
  • xét nghiệm khác liên quan đến việc đăng nhập/sử dụng phiên không bỏ buổi

bất cứ ai có thể cho tôi bất kỳ dẫn như những gì đang xảy ra ở đây chính xác, và lý do tại sao một trong những thử nghiệm chỉ có vẻ tự ý thả phiên và thất bại về tôi? Tôi đã thực hiện rất nhiều gỡ lỗi và đã thử mọi thứ tôi có thể nghĩ đến.

+0

Có sự cố tương tự ... argh ... – Lichtamberg

Trả lời

20

Tôi cũng mới với capybara và tôi cũng gặp sự cố tương tự.

Tôi đã cố gắng để đăng nhập người dùng làm một cái gì đó như thế này:

post user_session_path, :user => {:email => user.email, :password => 'superpassword'} 

Và đó đang làm việc ok cho đến khi tôi đã cố gắng để làm điều gì đó với Capybara, chẳng hạn như truy cập vào một trang và chỉ là thử nghiệm nếu người dùng đã đăng nhập in. Bài kiểm tra đơn giản này không được thông qua:

visit root_path 
page.should have_content("logout") #if the user is logged in then the logout link should be present 

Lúc đầu, tôi nghĩ capybara đã xóa các phiên nhưng tôi đã sai. Điều khiến tôi mất nhiều thời gian để nhận ra đó là trình điều khiển capybara đang xử lý các phiên riêng của nó, vì vậy, từ quan điểm của capybara người dùng của tôi chưa bao giờ đăng nhập. Để làm như vậy, bạn phải làm như thế này

page.driver.post user_session_path, :user => {:email => user.email, :password => 'superpassword'} 

Không chắc đây có phải là trường hợp của bạn hay không, nhưng hy vọng điều đó sẽ hữu ích.

+0

Cảm ơn ariera. Điều này làm việc cho tôi! – John

+0

Cảm ơn, ariera! Làm việc cho tôi quá. Đẹp sleuthing. – evanrmurphy

+2

nó có vẻ như ngừng hoạt động trong capybara sau này. Tôi đã có một cái gì đó như thsi lên và thống nhất tốt đẹp với một phiên bản trước 1. Bây giờ tôi nâng cấp lên 2.1 nó không thành công theo cách này. Cho đến ngày của câu trả lời này có khả năng nó đã được làm việc theo cách này từ capybara 1. Giải thích tốt! – froderik

7

Cách thủ công làm việc đó rất đơn giản:

it "does something after login" do 
    password = "secretpass" 
    user = Factory(:user, :password => password) 
    visit login_path 
    fill_in "Email", :with => user.email 
    fill_in "Password", :with => password 
    click_button "Log in" 
    visit # somewhere else and do something 
end 

Sau đó, bạn có thể phá vỡ này ra thành một chức năng trong 'spec_helper.rb' của bạn:

# at the bottom of 'spec_helper.rb' 
def make_user_and_login 
    password = "secretpass" 
    @user = Factory(:user, :password => password) 
    visit login_path 
    fill_in "Email", :with => @user.email 
    fill_in "Password", :with => password 
    click_button "Log in" 
end 

và sử dụng nó trong bất kỳ các bài kiểm tra của bạn (có thể yêu cầu thông số kỹ thuật):

it "does something after login" do 
    make_user_and_login 
    # now test something that requires a logged in user 
    # you have access to the @user instance variable 
end 
0

Đây có thể là một cảnh quay dài nhưng tôi tin rằng chúng tôi sẽ gặp tình trạng xấu sau click_button 'Sign in' và gọi ngay visit elsewhere ngay sau đó.

Lý thuyết của tôi là khi chúng tôi nhấp vào nút mà yêu cầu chưa hoàn thành và chúng tôi sẽ xóa nó bằng cách truy cập một đường dẫn khác.

Từ các tài liệu Capybara:

Khi phát hành hướng dẫn để các DSL như:

click_link('foo') click_link('bar') expect(page).to have_content('baz')

Nếu việc nhấp vào liên kết foo gây nên một quá trình không đồng bộ, chẳng hạn như một yêu cầu Ajax, trong đó, khi hoàn thành sẽ thêm liên kết thanh vào trang, nhấp vào liên kết thanh sẽ được dự kiến ​​sẽ không thành công, vì liên kết đó chưa tồn tại. Tuy nhiên Capybara đủ thông minh để thử tìm lại liên kết trong một khoảng thời gian ngắn trước khi từ bỏ và ném lỗi.

Nếu đây là giải pháp đơn giản: hãy cung cấp cho Capybara thứ gì đó để tìm và đợi cho đến khi yêu cầu hoàn tất. Điều này có thể đơn giản như thêm:

expect(page).to have_text('Signed in as [email protected]')

2

tôi đã có thể khắc phục lỗi này bằng cách thiết lập giá trị này là true trong config/initializers/test.rb

# Disable request forgery protection in test environment 
config.action_controller.allow_forgery_protection = true 

Trước đó, các CSRF <meta> các thẻ không được in ra <head>. Sau khi thay đổi giá trị này, cuối cùng chúng xuất hiện.

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