ruby-on-rails - gema - rails devise login
Diseñar "El token de confirmación no es válido" cuando el usuario se registra (3)
Usando Rails 4 y Devise 3.1.0 en mi aplicación web. Escribí una prueba de Cucumber para probar el registro de usuario; falla cuando se hace clic en el enlace "confirmar mi cuenta" desde el correo electrónico.
Scenario: User signs up with valid data # features/users/sign_up.feature:9
When I sign up with valid user data # features/step_definitions/user_steps.rb:87
Then I should receive an email # features/step_definitions/email_steps.rb:51
When I open the email # features/step_definitions/email_steps.rb:76
Then I should see the email delivered from "[email protected]" # features/step_definitions/email_steps.rb:116
And I should see "You can confirm your account email through the link below:" in the email body # features/step_definitions/email_steps.rb:108
When I follow "Confirm my account" in the email # features/step_definitions/email_steps.rb:178
Then I should be signed in # features/step_definitions/user_steps.rb:142
expected to find text "Logout" in "...Confirmation token is invalid..." (RSpec::Expectations::ExpectationNotMetError)
./features/step_definitions/user_steps.rb:143:in `/^I should be signed in$
Este error es reproducible cuando me suscribo manualmente a través del servidor web también, por lo que no parece ser un problema de Pepino.
Me gustaría:
- El usuario puede confirmar con un solo clic su cuenta a través del enlace de este correo electrónico
- Haga que el usuario permanezca conectado después de confirmar su cuenta
Tengo la configuración:
- El último código de Devise, de GitHub (3.1.0, ref 041fcf90807df5efded5fdcd53ced80544e7430f)
- Una clase de
User
que implementeconfirmable
- Uso del controlador de confirmación ''predeterminado'' (no he definido el mío propio).
He leído estas publicaciones:
- El diseño de confirmation_token no es válido
- Idea 3.1: ahora con valores predeterminados más seguros
- Problema de GitHub: idear confirmation_token inválido
Y lo he intentado:
- Estableciendo
config.allow_insecure_tokens_lookup = true
en mi inicializador Devise, que arroja un error de ''método desconocido'' al inicio. Además, parece que esto solo se supone que es una solución temporal, por lo que me gustaría evitar su uso. - Purgué mi DB y comencé desde cero (para que no haya tokens antiguos)
Actualizar:
Verificando el token de confirmación almacenado en el User
después de registrarse. El token de correos electrónicos coincide con el token de DBs. De acuerdo con las publicaciones anteriores, el nuevo comportamiento de Devise dice que no se supone que debe hacerlo, y que en su lugar debe generar un segundo token basado en el token del correo electrónico. Esto es sospechoso Ejecutar User.confirm_by_token(''[EMAIL_CONFIRMATION_TOKEN]'')
devuelve un usuario que tiene errores establecidos "@messages = {: confirmation_token => [" is invalid "]}", que parece ser el origen del problema.
Tokens que no coinciden parece ser el corazón del problema; ejecutar el siguiente código en la consola para cambiar manualmente la Confirmación de confirmación del usuario hace que la confirmación tenga éxito:
new_token = Devise.token_generator.digest(User, :confirmation_token, ''[EMAIL_TOKEN]'')
u = User.first
u.confirmation_token = new_token
u.save
User.confirm_by_token(''[EMAIL_TOKEN]'') # Succeeds
Entonces, ¿por qué está guardando el token de confirmación equivocado en el DB en primer lugar? Estoy usando un controlador de registro personalizado ... ¿tal vez hay algo en él que hace que se establezca incorrectamente?
routes.rb
devise_for :users,
:path => '''',
:path_names => {
:sign_in => ''login'',
:sign_out => ''logout'',
:sign_up => ''register''
},
:controllers => {
:registrations => "users/registrations",
:sessions => "users/sessions"
}
users / registrations_controller.rb :
class Users::RegistrationsController < Devise::RegistrationsController
def create
# Custom code to fix DateTime issue
Utils::convert_params_date_select params[:user][:profile_attributes], :birthday, nil, true
super
end
def sign_up_params
# TODO: Still need to fix this. Strong parameters with nested attributes not working.
# Permitting all is a security hazard.
params.require(:user).permit!
#params.require(:user).permit(:email, :password, :password_confirmation, :profile_attributes)
end
private :sign_up_params
end
A partir del dispositivo 3.5.2, el token de confirmación ya no se digiere durante el proceso de confirmación. Esto significa que el token en el correo electrónico coincidirá con el token en la base de datos.
Todavía tenía problemas con las confirmaciones después de descubrir esto, pero en mi caso resultó ser un error que introduje cuando find_first_by_auth_conditions
. Al corregir el error que introduje en ese método, corregí mis errores con confirmación.
Así que actualizar a Devise 3.1.0 dejó un poco de ''cruft'' en una vista que no había tocado en mucho tiempo.
De acuerdo con esta publicación del blog , debe cambiar su correo de Devise para usar @token
lugar del antiguo @resource.confirmation_token
.
Encuentre esto en la app/views/<user>/mailer/confirmation_instructions.html.erb
y cámbielo a algo como:
<p>Welcome <%= @resource.email %>!</p>
<p>You can confirm your account email through the link below:</p>
<p><%= link_to ''Confirm my account'', confirmation_url(@resource, :confirmation_token => @token) %></p>
Esto debería solucionar cualquier problema de confirmación basado en token que estés teniendo. Es probable que también solucione cualquier problema de desbloqueo o restauración de token de contraseña.
Un amigo mío acaba de encontrar esta pregunta y me envió un correo electrónico preguntándome si me había dado cuenta de esto, lo que me recordó que nunca presenté mi propia respuesta, así que aquí va :)
Terminé restableciendo el token y usando send
para obtener el token en bruto. Es feo, pero funciona en un golpe para el devise (3.5.1)
.
26 it "should auto create org" do
27 email = FG.generate :email
28 visit new_user_registration_path
29 fill_in :user_name, with: ''Ryan Angilly''
30 fill_in :user_user_provided_email, with: email
31 fill_in :user_password, with: ''1234567890''
32
33 expect do
34 click_button ''Continue''
35 end.to change { Organization.count }.by(1)
36
37 expect(page.current_path).to eq(confirmation_required_path)
38 u = User.where(email: email).first
39 u.send :generate_confirmation_token
40 email_token = u.instance_variable_get(:@raw_confirmation_token)
41 u.save!
42 os = u.organizations
43 expect(os.size).to eq(1)
44 visit user_confirmation_path(confirmation_token: email_token)
45 o = os.first
46
47 u.reload
48 expect(u.confirmed?)
49 expect(page.current_url).to eq(organization_getting_started_url(o))
50 end