grails bcrypt

grails - Bcrypt genera hashes diferentes para la misma entrada?



(2)

Jan es correcto: bcrypt por diseño no genera el mismo hash para cada cadena de entrada. Pero hay una manera de verificar que una contraseña hash sea válida y esté incorporada en el codificador de contraseña asociado. Así que agrega una inyección de dependencia para el bean passwordEncoder en tu controlador ( def passwordEncoder ) y cambia la búsqueda a

def handleLogin = { if (springSecurityService.isLoggedIn()) { render(view: "../homepage") return } def user = Registration.findByEmail(params.email) if (user && !passwordEncoder.isPasswordValid(user.password, params.password, null)) { user = null } if (!user) { flash.message = "User not found for email: ${params.email}" render(view: "../index") return } session.user = user render(view: "../homepage") }

Tenga en cuenta que no codifica la contraseña para la llamada isPasswordValid - pase en la contraseña presentada sin cifrado.

Además, sin relación alguna, es una mala idea almacenar al usuario en la sesión. El principal de autenticación está disponible y almacena la identificación del usuario para facilitar la recarga del usuario según sea necesario (por ejemplo, User.get(springSecurityService.principal.id) . Almacenar objetos de Hibernate potencialmente grandes desconectados funciona muy bien en el modo dev cuando eres el único usuario de su servidor, pero puede ser una pérdida significativa de memoria y lo obliga a trabajar alrededor de los objetos que se desconectan (por ejemplo, tener que usar merge , etc.).

Acabo de agregar una funcionalidad de registro a mi nuevo proyecto Grails. Para probarlo, me registré dando un correo electrónico y una contraseña. Estoy usando algoritmo bcrypt para hash la contraseña antes de guardarla en la base de datos.

Sin embargo, cuando intento iniciar sesión con el mismo correo electrónico y la misma contraseña que proporcioné durante el registro, el inicio de sesión falla. Depuré la aplicación y descubrí que el hash que se genera para la misma contraseña es diferente cuando trato de compararlo con el hash de la base de datos y, por lo tanto, el inicio de sesión está fallando ( Registration.findByEmailAndPassword (params.email, hashPassd) en LoginController .groovy devuelve nulo ).

Aquí está mi clase de dominio Registration.groovy:

class Registration { transient springSecurityService String fullName String password String email static constraints = { fullName(blank:false) password(blank:false, password:true) email(blank:false, email:true, unique:true) } def beforeInsert = { encodePassword() } protected void encodePassword() { password = springSecurityService.encodePassword(password) } }

Aquí está mi LoginController.groovy:

class LoginController { /** * Dependency injection for the springSecurityService. */ def springSecurityService def index = { if (springSecurityService.isLoggedIn()) { render(view: "../homepage") } else { render(view: "../index") } } /** * Show the login page. */ def handleLogin = { if (springSecurityService.isLoggedIn()) { render(view: "../homepage") return } def hashPassd = springSecurityService.encodePassword(params.password) // Find the username def user = Registration.findByEmailAndPassword(params.email,hashPassd) if (!user) { flash.message = "User not found for email: ${params.email}" render(view: "../index") return } else { session.user = user render(view: "../homepage") } } }

Aquí hay un fragmento de mi Config.groovy que le dice a Grails que use el algoritmo bcrypt para usar contraseñas hash y el número de rondas de codificación:

grails.plugins.springsecurity.password.algorithm = ''bcrypt'' grails.plugins.springsecurity.password.bcrypt.logrounds = 16


Un hash BCrypt incluye salt y, como resultado, este algoritmo devuelve hashes diferentes para la misma entrada. Permíteme demostrarlo en Ruby.

> require ''bcrypt'' > p = BCrypt::Password.create "foobar" => "$2a$10$DopJPvHidYqWVKq.Sdcy5eTF82MvG1btPO.81NUtb/4XjiZa7ctQS" > r = BCrypt::Password.create "foobar" => "$2a$10$FTHN0Dechb/IiQuyeEwxaOCSdBss1KcC5fBKDKsj85adOYTLOPQf6" > p == "foobar" => true > r == "foobar" => true

En consecuencia, BCrypt no se puede utilizar para buscar usuarios de la manera que se muestra en su ejemplo. En su lugar, debería usarse un campo alternativo no ambiguo, por ejemplo, el nombre del usuario o la dirección de correo electrónico.