2013-09-06 30 views
34

Tôi đang sử dụng đá quý devise, sau khi nhấp vào liên kết xác nhận, tôi muốn đăng nhập trực tiếp. Hiện tại, yêu cầu đăng nhập lại.Tránh đăng nhập sau khi nhấp vào liên kết xác nhận bằng cách sử dụng đá quý devise?

Gần đây tôi đã thêm sau trong devise khởi tạo file:

config.allow_insecure_token_lookup = true 
config.secret_key = 'a8d814803c0bcc735ce657adc77793459d00154cdd7532c13d3489600dc4e963f86e14beb593a32cbe9dbbe9197c9ce50a30102f363d90350052dc8d69930033' 

Bất kỳ lời đề nghị?

+0

liên kết xác nhận của bạn có chứa bất kỳ 'mã thông báo truy cập' nào không? –

+1

có, liên kết ví dụ: http: // localhost: 3000/người dùng/xác nhận? Confirmation_token = ede7fbc3203644c0ff40cf31844389d460607a09d5f13ce95bcddd25c8fce667 –

Trả lời

54

Trong các phiên bản Devise trước đó, người dùng được tự động đăng nhập sau khi xác nhận. Điều này có nghĩa là bất kỳ ai có thể truy cập email xác nhận đều có thể đăng nhập vào tài khoản của ai đó bằng cách nhấp vào liên kết.

Tự động đăng nhập người dùng cũng có thể có hại trong quy trình xác nhận lại email. Hãy tưởng tượng rằng một người dùng quyết định thay đổi địa chỉ e-mail của mình và, trong khi làm như vậy, anh ta đánh máy vào địa chỉ e-mail mới. Một e-mail sẽ được gửi đến một địa chỉ khác, với mã thông báo trong tay, sẽ có thể đăng nhập vào tài khoản đó.

Nếu người dùng sửa ngay e-mail, sẽ không có tác hại nào được thực hiện. Nhưng nếu không, ai đó có thể đăng nhập vào tài khoản đó và người dùng sẽ không biết rằng nó đã xảy ra.

Vì lý do này, Devise 3.1 không còn tự động đăng nhập người dùng sau khi xác nhận. Bạn có thể tạm thời mang lại các hành vi cũ trở lại sau khi nâng cấp bằng cách thiết lập sau trong cấu hình của bạn/initializers/devise.rb:

config.allow_insecure_sign_in_after_confirmation = true

Tùy chọn này sẽ có mặt chỉ tạm thời để hỗ trợ di dân.

+1

Nó hoạt động tốt. Cảm ơn bạn rất nhiều Rajarshi Das! Giúp đỡ nhiều. –

+1

Tôi đã đi điên đào thông qua nguồn gốc và không thể tìm thấy nơi nó được đăng nhập người dùng sau khi xác nhận. Và nó không phải là, cảm ơn bạn đã làm cho rõ ràng! – Mirko

+1

Nếu bạn có thể truy cập vào tài khoản email của người dùng, bạn có thể đặt lại mật khẩu của mình, vì vậy, tôi không hiểu là tôi đã hiểu vấn đề bảo mật tại đây. Tương tự cho ví dụ thứ hai, nếu bạn nhận được email để xác nhận thay đổi địa chỉ email, bạn có thể thay đổi mật khẩu sau cùng một vấn đề. – Jean

51

Cờ config.allow_insecure_sign_in_after_confirmation không còn được hỗ trợ trong Devise nữa.

Mặc dù bạn phải biết các mối lo ngại về bảo mật có thể tự động đăng nhập người dùng khi họ xác nhận tài khoản của họ (http://blog.plataformatec.com.br/2013/08/devise-3-1-now-with-more-secure-defaults/), đối với một số ứng dụng, lợi ích về trải nghiệm người dùng có thể đáng giá. Sau khi tất cả, nguy cơ bảo mật là a) người dùng đánh sai email của họ, b) họ không sửa lỗi ngay lập tức, c) email họ đã nhập tương ứng với email hợp lệ và đang hoạt động, d) người nhận không chính xác email sẽ mở ra và nhấp vào liên kết.

Nếu đây là một hồ sơ rủi ro có thể chấp nhận cho ứng dụng của bạn, bạn có thể ghi đè lên ConfirmationsController devise:

class ConfirmationsController < Devise::ConfirmationsController 
    def show 
    self.resource = resource_class.confirm_by_token(params[:confirmation_token]) 
    yield resource if block_given? 

    if resource.errors.empty? 
     set_flash_message(:notice, :confirmed) if is_flashing_format? 
     sign_in(resource) # <= THIS LINE ADDED 
     respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource) } 
    else 
     respond_with_navigational(resource.errors, :status => :unprocessable_entity){ render :new } 
    end 
    end 
end 

Và con đường để nó trong routes.rb của bạn:

devise_for :users, controllers: { confirmations: 'confirmations' } 
+0

Tại sao không thể đưa ra một cái gì đó để xác định rằng máy đang liên kết trên, là cùng một máy khiến email được gửi đi? Ví dụ: lưu một thứ gì đó trong cookie. Sau đó, nếu máy khớp, hãy đăng nhập tự động và nếu không, hãy yêu cầu đăng nhập. – brooks

+0

Thực hiện tốt @LouisSimoneau! – josethernandezc

+3

Nếu bạn đang làm điều này, nó có giá trị thay đổi chuỗi 'en: devise: confirmations: confirmed' trong' config/locales/devise.en.yml' để nói rằng bạn cũng đã đăng nhập chúng vào ... –

15

Với nhiều phiên bản gần đây của lập mưu , bạn có thể làm như sau.

config/routes.rb:

devise_for :users, controllers: { confirmations: 'users/confirmations' } 

app/controllers/người dùng/confirmations_controller.rb:

class Users::ConfirmationsController < Devise::ConfirmationsController 
    def show 
    super do |resource| 
     sign_in(resource) 
    end 
    end 
end 
+0

Tôi khá chắc chắn điều này sẽ không thực sự hoạt động như dự định: lệnh gọi 'yield' trong ConfirmationsController của Devise xảy ra _whether hoặc not_ tài nguyên có lỗi, vì vậy tôi nghĩ rằng điều này sẽ giúp bạn đăng nhập ngay cả khi không có xác nhận đúng mã thông báo (!!!). –

+2

Có, điều đó sẽ đăng nhập bất kể mã thông báo có hợp lệ hay không. Nhưng bạn có thể khắc phục điều đó bằng cách thay đổi dòng sign_in thành 'sign_in (resource) nếu resource.errors.empty? ' – scottwb

+0

Thực ra nó không ký tên người dùng trong đó mã thông báo có hợp lệ hay không. Nó mang lại tài nguyên, nhưng tất cả các trường là nil (vì 'Devise' không thể tìm thấy' User' với mã thông báo liên quan). Vì vậy, bạn sẽ được chuyển hướng đến đường dẫn sign_in (theo mặc định) với thông báo cho biết bạn cần phải xác nhận tài khoản của mình. Bây giờ, với điều đó đã nói, tôi nghĩ rằng thêm 'if resource.errors.empty? 'Là ý định độc đáo tiết lộ, nhưng, nó là không cần thiết. –

1

Chúng tôi muốn người dùng đăng nhập tự động nếu cô ấy nhấp vào liên kết trong email 2 giờ hoặc ít hơn sau khi tạo người dùng. Dựa trên @ câu trả lời Sjor, chúng tôi đã đi với:

class ConfirmationsController < Devise::ConfirmationsController 
    def show 
    super do |resource| 
     if resource.confirmed_at > DateTime.now-2.hours && resource.errors.empty? 
     sign_in(resource) 
     end 
    end 
    end 
end 
3

Nhìn vào câu trả lời mb21, nó nên

def show 
    super do |resource| 
    if resource.confirmation_sent_at > DateTime.now-2.hours && resource.errors.empty? 
     sign_in(resource) 
    end 
    end 
end 

confirmation_sent_at là lần email đã được gửi đến người sử dụng, như trái ngược với confirmed_at, mà là thời điểm người dùng nhấp vào liên kết, luôn trong vòng 2 giờ kể từ bây giờ trên máy chủ khi nó xảy ra ...