Introducción Las cuentas de usuario son una característica indispensable de las aplicaciones web. Nos permiten crear experiencias personalizadas y persistentes para las personas que utilizan nuestro sitio. También nos ayudan a realizar un mejor seguimiento de cómo se utiliza nuestra aplicación. A pesar de su utilidad, implementar cuentas de usuario puede ser como abrir la caja de problemas de Pandora. Vivimos en una era de saqueadores inteligentes de dominios digitales. Si bien hemos abierto una caja de posibilidades, ¡han traído consigo una gran cantidad de problemas! ¿Cómo tenemos una oportunidad? Nos apoyamos en el trabajo de otros y en la configuración comercial por convención. Pero antes de encontrar algunos hombros en los que apoyarnos, tengamos una idea del problema que estamos tratando de resolver. Registrarse e iniciar sesión y son acciones con las que todos estamos familiarizados. Permiten que las aplicaciones web y a sus usuarios. Registrarse Iniciar sesión autentiquen autoricen Cuando nos , creamos un medio por el cual una aplicación web determina que somos quienes decimos que somos. El registro ocurre una vez en la vida de un usuario en una aplicación. Crea una nueva instancia de usuario en el backend del servidor con información que se puede usar para a ese usuario. La autenticación hace la pregunta: "¿Eres quien dices ser?" Cuando iniciamos sesión, somos autenticados por la aplicación en función del nombre de usuario y la contraseña que proporcionamos y, en consecuencia, tenemos acceso a diferentes funciones de la aplicación. registramos autenticar Estamos comprometidos con cuando solo tenemos que proporcionar un tipo de información para autenticarnos. Como puede imaginar, la autenticación de un solo factor no es el mejor medio para proteger las cuentas de usuario, ya que cualquier persona con un nombre de usuario y una contraseña puede acceder a una cuenta. la autenticación de un solo factor Ahí es donde entra en juego la autenticación . Nos encontramos con la autenticación multifactor bastante bien todos los días, cuando un sitio nos pide que ingresemos un código generado aleatoriamente que se envía a nuestros teléfonos además de nuestro nombre de usuario y contraseña, o cuando un cajero automático requiere que ingresemos un número PIN e insertemos nuestro débito. tarjeta. No construiremos la autenticación multifactor en esta publicación, pero es importante tenerlo en cuenta. multifactor Una vez que iniciamos sesión y nos autenticamos mediante una aplicación, verificará si estamos para realizar las acciones que intentamos realizar. La autorización hace la pregunta: "¿Tienes permiso para hacer eso?" El medio por el cual una aplicación web autoriza a un usuario es a través de cookies, en concreto, cookies de sesión. autorizados Una cookie es un bit de datos almacenados en el navegador de un usuario. Las aplicaciones web pueden almacenar todo tipo de información en cookies para rastrear el estado y el historial de un usuario. Una cookie de sesión es una cookie que dura la duración de una sesión en una aplicación web, generalmente desde el inicio de sesión/inicio de sesión hasta el inicio de sesión/cierre de sesión. Cuando un usuario inicia sesión, el navegador del usuario recibe una cookie de la aplicación web que identifica a ese usuario. La autorización del usuario se puede verificar cuando se realizan solicitudes HTTP de la aplicación. El registro ocurre una vez en la vida del usuario en una aplicación web. Le da a la aplicación un medio para autenticar al usuario, o verificar que sea quien dice ser, a través de un nombre de usuario, contraseña y cualquier otra información requerida. Cuando un usuario inicia sesión, se autentica y recibe una cookie de sesión de identificación. A medida que el usuario interactúa con la aplicación, la aplicación puede verificar si el usuario está autorizado o autorizado para realizar una acción al hacer referencia a la cookie del usuario. Autenticación con bcrypt La autenticación es la forma que tiene una aplicación web de comprobar que un usuario es quien dice ser. Hay varias gemas de Ruby ya escritas para facilitar este proceso. es uno de los más populares, junto con y . Devise Omniauth Doorkeeper ¡No vamos a usar ninguno de esos! Con el fin de comprender el proceso de autenticación y autorización, usaremos una gema que lo ha estado observando desde que abrió por primera vez un Rails Gemfile: . bcrypt ¡Descomenta a ese tipo! source git_source( ) { } ... gem , ... 'https://rubygems.org' :github |repo| "https://github.com/ .git" #{repo} # ruby '2.5.1' # Use Redis adapter to run Action Cable in production # gem 'redis', '~> 4.0' # Use ActiveModel has_secure_password 'bcrypt' '~> 3.1.7' # Use ActiveStorage variant # gem 'mini_magick', '~> 4.8' la gema de Ruby se basa en bcrypt, el algoritmo hash de OpenBSD. Dada cualquier cadena, como una contraseña, el hash codificará la cadena junto con una pizca de caracteres aleatorios (conocidos como sal) de tal manera que el proceso no se pueda revertir o adivinar. bcrypt la gema de Ruby nos permite utilizar el algoritmo bcrypt para hash de contraseñas, y también gestiona el almacenamiento de la sal utilizada en el hashing para que luego podamos autenticar a nuestros usuarios. bcrypt pw = BCrypt::Password.create( ) pw == 'P4ssW02d!' # => "$2a$12$YNW0EG8VwLmy1l9yxMeyAOaen/Yhx7LTBJR6G7jnG2WMkr9fo7aO6" 'P4ssW02d!' # => true bcrypt y el modelo de usuario Para usar , nuestra tabla de usuario debe tener un atributo. En sus proyectos de Rails, puede ejecutar lo siguiente: . bcrypt password_digest rails generate resource User username password_digest Después de migrar la tabla, deberíamos tener un esquema similar al siguiente: create_table , t.string t.string t.datetime , t.datetime , "users" force: :cascade do |t| "username" "password_digest" "created_at" null: false "updated_at" null: false end Tenga en cuenta que estamos almacenando un resumen de contraseña, no una contraseña. Nunca, nunca, por el motivo que sea, aunque tu madre también te lo pida, aunque creas que te curará los hongos en los pies, nunca guardes las contraseñas en texto sin formato. También debemos agregar a nuestro modelo de usuario. Notará que he agregado algunas validaciones para garantizar que nuestros usuarios se creen con un nombre de usuario único y una contraseña no única. requiera contraseñas únicas, ya que les dará a los ineptos la información y la confianza que necesitan para obtener acceso a las cuentas de los usuarios. has_secure_password No has_secure_password validates , , validates , < ApplicationRecord class User :username presence: true uniqueness: true :password presence: true end es un método auxiliar para modelos que les da acceso a métodos que ayudarán en la autenticación. Podemos probarlos en . has_secure_password rails console usr = User.create( , , ) usr.authenticate( ) usr.authenticate( ) username: "cheetochester" password: "Ch33zy$" password_confirmation: "Ch33zy$" # => #<User id: 4, username: "cheetochester", password_digest: "$2a$12$Io.kXzHPXoGZYzuWBawSFOawjvGNmsrHsCiXbNhlYep..." ...> "cheesys" # => false "Ch33zy$" # => #<User id: 4, username: "cheetochester", password_digest: "$2a$12$Io.kXzHPXoGZYzuWBawSFOawjvGNmsrHsCiXbNhlYep..." ...> Tenga en cuenta que cuando creamos un nuevo usuario, lo hacemos con el y llaves, no . password password_confirmation password_digest maneja la validación de la contraseña y y convertir la contraseña en el que se guarda en la base de datos. Dada una cadena de contraseña, el El método devuelve falso si la contraseña es incorrecta y la instancia de usuario si la contraseña es correcta. bcrypt password_confirmation password_digest #authenticate Rutas Antes de que podamos configurar con confianza nuestros controladores, debemos tener una visión clara de nuestras rutas. En esta aplicación de ejemplo básica, los usuarios pueden crear y ver sus cuentas. También pueden iniciar y cerrar sesión en sus cuentas. Manejaremos esta funcionalidad con las siguientes rutas en : rails-app/config/routes.rb Rails.application.routes.draw resources , [ , ] get , get , post , delete , do :users only: :create :show "/signup" to: "users#new" "/login" to: "sessions#new" "/sessions" to: "sessions#create" "/sessions" to: "sessions#destroy" # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end Crear un formulario de registro El extracto de código a continuación muestra un controlador de usuario básico. Hemos admitido acciones para crear un usuario y ver su página. @user = User.new @user = User.create(user_params) @user.valid? @user.save redirect_to @user redirect @user = User.find(params[ ]) private params. ( ).permit( , , ) < ApplicationController class UsersController def new end def create if else :new end end def show :id end def user_params require :user :username :password :password_confirmation end end No hay salsa especial para crear un formulario de registro. Simplemente necesitamos un formulario que pase , , y a nuestra aplicación. En podemos generar un formulario con ayudantes de formulario de Rails así: username password password_confirmation rails-app/app/views/users/new.html.erb <%= form_for @user %> <%= f.label %> <%= f.text_field , %> <%= f.label %> <%= f.password_field , %> <%= f.label %> <%= f.password_field , %> <%= f.submit %> <% %> do |f| :username :username placeholder: "Username" :password :password placeholder: "Password" :password_confirmation :password_confirmation placeholder: "Confirm Password" "Create Account" end En la presentación, nuestro action intentará crear una nueva instancia de usuario con esos parámetros. Si la instancia de usuario es válida, el usuario será redirigido a su página de presentación. De lo contrario, el usuario será redirigido a la página de nuevo usuario. UsersController#create Iniciando sesión El inicio de sesión o el inicio de sesión se gestionará a través de Rails. hash, que lee y gestiona un cookie en el navegador de un usuario. Administrar la sesión requiere suficientes acciones únicas para justificar otro controlador. Llamaremos a este controlador el . session session SessionsController @user = User.find_by( params[ ]) @user && @user.authenticate(params[ ]) session[ ] = @user.id redirect_to @user redirect_to login_path < ApplicationController class SessionsController def new end def create username: :username if :password :user_id else end end end En este controlador hemos definido dos acciones. es simplemente responsable de mostrar una página que permite a un usuario crear una nueva sesión (también conocida como inicio de sesión). SessionsController#new Los contenidos de tal vez tan simple como: rails-app/app/views/sessions/new.html.erb <%= form_tag sessions_path %> <%= label_tag %> <%= text_field_tag , , %> <%= label_tag %> <%= password_field_tag , , %> <%= submit_tag %> <% %> do "Username" :username nil placeholder: "Username" "Password" :password nil placeholder: "Password" "Log In" end El propósito de este formulario es solicitar la autenticación de un usuario y el almacenamiento de su identidad en el Galleta. session En , primero intentamos encontrar al usuario en función de su nombre de usuario. Si el usuario existe, lo autenticamos mediante la contraseña facilitada en el formulario y el método que nos otorga el joya. Si están autenticados, almacenaremos su identificación en la cookie de sesión ( ). SessionsController#create #authenticate bcrypt session[:user_id] = @user.id De lo contrario, serán redirigidos a la ruta de inicio de sesión. ¿Qué evita que alguien simplemente modifique su cookie de sesión para imitar a un usuario? ¡Por suerte para nosotros, Rails encripta las cookies que crea! Sentando las bases para la autorización con bcrypt Implementamos la autenticación con un par de formularios, un puñado de rutas y acciones de controlador, y algunas métodos. Y sin embargo, un pájaro de un solo ala no puede volar. Necesitamos autorización para poner a funcionar nuestra autenticación. bcrypt Podemos sentar las bases para la autorización escribiendo métodos auxiliares en . rails-app/app/controllers/application_controller.rb helper_method , session[ ] @user = User.find(session[ ]) !!current_user redirect_to login_path logged_in? < ActionController::Base class ApplicationController :logged_in? :current_user def current_user if :user_id :user_id end end def logged_in? end def authorized unless end end Aquí hemos definido algunos métodos auxiliares para usar en nuestros controladores y vistas. busca un valor en el clave de la hachís de galletas. Si hay uno, se devolverá la instancia de usuario correspondiente. ApplicationController#current_user :user_id session De lo contrario, el valor de retorno es . coacciona el valor de retorno de en un valor booleano mediante el uso de un doble golpe. nil #logged_in? current_user activará una redirección a la página de inicio de sesión a menos que un usuario haya iniciado sesión (es decir, a menos que un valor de existe y coincide con el valor de una identificación de un usuario existente) #authorized session[:user_id] Autorización en Controladores los El método de devolución de llamada puede ayudarnos a simplificar el uso de nuestros métodos de autorización. En nuestro , agregaremos: before_action UsersController before_action , [ ] ... < ApplicationController class UsersController :authorized only: :show end Con esta línea, la aplicación verificará si un usuario ha iniciado sesión y lo redirigirá a la ruta de inicio de sesión si no lo está antes de la incluso se dispara la acción. Pero la diversión no se detiene aquí. ¡Podemos aprovechar nuestros métodos auxiliares de autorización para representar condicionalmente nuestras vistas! #show Autorización en Vistas En , agreguemos un botón de inicio/cierre de sesión debajo de nuestra plantilla de vista. De esa manera, aparecerá en cualquier página que agreguemos a nuestra aplicación. rails-app/app/views/layouts/application.html.erb Recordar que en es donde se representan las plantillas correspondientes a las acciones de nuestro controlador. <%= yield %> application.html.erb <!DOCTYPE html> <html> ... <body> <%= %> <br> <% logged_in? %> <%= button_to , sessions_path, %> <% %> <%= button_to , login_path, %> <% %> < > yield if "Logout" method: :delete else "Login Page" method: :get end /body> </html Ya que definimos el método auxiliar y aprobado como argumento para en nuestro , podemos usarlo en nuestras vistas. este poco de muestra un botón de cierre de sesión si un usuario ha iniciado sesión y viceversa. #logged_in? :logged_in? helper_method ApplicationController erb Podemos ser aún más específicos. Ya que tenemos un método auxiliar que devuelve el usuario de la sesión actual, podemos generar contenido personalizado para ese usuario. current_user Sobre el página, podemos hacer que un usuario vea contenido especial si está en su propia página de presentación. rails-app/app/views/users/show.html.erb <h1>Welcome to the page of <%= @user.username %>< 3> <% % /h2> <% if current_user == @user %> <h3>This is my page!!!</h end Saliendo de tu cuenta Toda buena historia tiene que llegar a su fin. Cuando un usuario cierra la sesión, esencialmente está finalizando su . Una forma básica de finalizar la sesión de un usuario es establecer el valor de a . Agregaremos la siguiente acción a nuestro para hacerlo session session[:user_id] nil SessionsController ... session[ ] = redirect_to login_path < ApplicationController class SessionsController def destroy :user_id nil end end Si es del tipo observador, habrá notado que el botón de cierre de sesión que creamos en la última sección realiza la solicitud HTTP que se enrutará a esta acción. Con esa acción, la cookie de sesión dejará de saber sobre el usuario y el usuario no estará autorizado en la aplicación. Conclusión Y eso es todo lo que se necesita para desarrollar la autenticación y autorización básicas en una aplicación Rails con ! Cuando autenticamos a un usuario, verificamos que sea quien dice ser. Facilitamos la autenticación en una aplicación web a través de formularios de registro e inicio de sesión. Para hacer uso de la autenticación, rastreamos el estado del usuario en una cookie de sesión y usamos esa cookie para realizar la autorización antes de las acciones relevantes en nuestra aplicación. bcrypt nos ayuda a implementar la autenticación brindándonos un medio para almacenar de forma segura y hacer referencias cruzadas de factores de autenticación (como contraseñas) en nuestra base de datos. Para autorizar a los usuarios, escribimos métodos de ayuda que utilizan algunos de esos medios, así como la cookie de sesiones de Rails integrada para verificar el estado del usuario y reaccionar en consecuencia. bcrypt Ahora que tiene una idea de cómo funciona, intente implementarlo usted mismo. Cuando te sientas cómodo usando , romper las armas grandes como e intenta de nuevo. La autenticación y la autorización son partes esenciales de las aplicaciones web seguras. bcrypt devise Todos estaremos mejor si los usas. Y nunca almacene contraseñas de texto sin formato en una base de datos.