Abordar la autenticación con Vue utilizando API RESTful
La autenticación (¡iniciar sesión!) es una parte crucial de muchos sitios web. Veamos cómo hacerlo en un sitio usando Vue, de la misma manera que se puede hacer con cualquier back-end personalizado. En realidad, Vue no puede realizar la autenticación por sí solo; Necesitaremos otro servicio para eso, por lo que usaremos otro servicio (Firebase) para eso, pero luego integraremos toda la experiencia en Vue.
La autenticación funciona de manera bastante diferente en aplicaciones de página única (SPA) que en sitios que recargan cada página. No es necesario crear un SPA con Vue, pero lo haremos en este tutorial.
Aquí está el plan. Crearemos una interfaz de usuario para que los usuarios inicien sesión y los datos enviados se enviarán a un servidor para verificar si el usuario existe. En caso afirmativo, nos enviarán una ficha. Esto es muy útil porque se utilizará en todo nuestro sitio para comprobar si el usuario todavía ha iniciado sesión. Si no, el usuario siempre podrá registrarse. En otras palabras, se puede utilizar en muchos contextos condicionales. Más allá de eso, si necesitamos información del servidor que requiere iniciar sesión, el token se envía al servidor a través de la URL para que la información solo pueda enviarse a los usuarios que hayan iniciado sesión.
La demostración completa de este tutorial está publicada en GitHub para aquellos que se sienten cómodos leyendo el código. El resto de nosotros podemos seguir adelante con el artículo. El archivo de inicio también está en GitHub para que pueda seguirlo mientras codificamos juntos.
Después de descargar el repositorio, lo ejecutará npm install
en su terminal. Si va a crear esta aplicación completamente por su cuenta, deberá instalar Vuex, Vue Router y axios. También usaremos Firebase para este proyecto, así que tomaremos un momento para configurar una cuenta gratuita y crear un nuevo proyecto allí.
Después de agregar el proyecto a Firebase, vaya a la sección de autenticación y configure un método de inicio de sesión en el que usaríamos el proveedor tradicional de correo electrónico/contraseña, que se almacenará en nuestros servidores de Firebase.
Después de eso, iremos a la documentación de la API REST de Firebase Auth para obtener nuestros puntos finales de API de registro e inicio de sesión. Necesitaremos una clave API para usar esos puntos finales en nuestra aplicación y se puede encontrar en la configuración del proyecto de Firebase.
Firebase ofrece autenticación a través del SDK, pero utilizamos la API de autenticación para demostrar la autenticación a través de cualquier servidor back-end personalizado.
En nuestro archivo stater, tenemos el formulario de registro a continuación. Mantenemos las cosas bastante simples aquí ya que nos enfocamos en aprender los conceptos.
template div div form @submit.prevent="onSubmit" div label for="email"Mail/label input type="email" v-model="email" /div div label for="name"Your Name/label input type="text" v-model.number="name" /div div label for="password"Password/label input type="password" v-model="password" /div div button type="submit"Submit/button /div /form /div /div/template
Si no estuviéramos trabajando con un SPA, naturalmente usaríamos axios para enviar nuestros datos dentro de la etiqueta script de esta manera:
axios.post('https://identitytoolkit.googleapis.com/v1/account s:signUp?key=[API_KEY]', { email: authData.email, password: authData.password, returnSecureToken: true }) .then(res = { console.log(res) }) .catch(error = console.log(error)) }}
Regístrate e inicia sesión
Trabajar con un SPA (usando Vue en este caso) es muy diferente del enfoque anterior. En su lugar, enviaremos nuestras solicitudes de autorización utilizando Vuex en nuestras acciones en el store.js
archivo. Lo hacemos de esta manera porque queremos que toda la aplicación esté al tanto de cualquier cambio en el estado de autenticación del usuario.
actions: { signup ({commit}, authData) { axios.post('https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=[API_KEY]', { email: authData.email, password: authData.password, returnSecureToken: true }) .then(res = { console.log(res) router.push("/dashboard") }) .catch(error = console.log(error)) }, login ({commit}, authData) { axios.post(https://identitytoolkit.googleapis.com/v1/accounts:signIn?key=[API_KEY]', { email: authData.email, password: authData.password, returnSecureToken: true }) .then(res = { console.log(res) router.push("/dashboard") }) .catch(error = console.log(error)) }}
Podemos usar prácticamente lo mismo para el método de inicio de sesión, pero usando el punto final de API de inicio de sesión. Luego enviamos tanto el registro como el inicio de sesión desde los componentes a sus respectivas acciones en la tienda.
methods : { onSubmit () { const formData = { email : this.email, name : this.name, password : this.password } this.$store.dispatch('signup', formData) } }}
formData
contiene los datos del usuario.
methods : { onSubmit () { const formData = { email : this.email, password : this.password } this.$store.dispatch('login', {email: formData.email, password: formData.password}) }}
Estamos tomando los datos de autenticación (es decir, el token y la identificación del usuario) que se recibieron del formulario de registro/inicio de sesión y los usamos como estado con Vuex. Inicialmente resultará como null
.
state: { idToken: null, userId: null, user: null}
Ahora creamos un nuevo método llamado authUser
mutaciones que almacenará los datos recopilados de la respuesta. Necesitamos importar el enrutador a la tienda, ya que lo necesitaremos más adelante.
import router from '/router'
mutations : { authUser (state, userData) { state.idToken = userData.token state.userId = userData.userId }}
Dentro del .then
bloque en los métodos de registro/inicio de sesión en nuestras acciones, enviaremos nuestra respuesta a la authUser
mutación que acabamos de crear y la guardaremos en el almacenamiento local.
actions: { signup ({commit}, authData) { axios.post('https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=[API_KEY]'), { email: authData.email, password: authData.password, returnSecureToken: true }) .then(res = { console.log(res) commit('authUser', { token: res.data.idToken, userId: res.data.localId }) localStorage.setItem('token', res.data.idToken) localStorage.setItem('userId', res.data.localId) router.push("/dashboard") }) .catch(error = console.log(error)) }, login ({commit}, authData) { axios.post('https://identitytoolkit.googleapis.com/v1/accounts:signIn?key=[API_KEY]'), { email: authData.email, password: authData.password, returnSecureToken: true }) .then(res = { console.log(res) commit('authUser', { token: res.data.idToken, userId: res.data.localId }) localStorage.setItem('token', res.data.idToken) localStorage.setItem('userId', res.data.localId) router.push("/dashboard") }) .catch(error = console.log(error)) }}
Configurar una guardia de autenticación
Ahora que tenemos nuestro token almacenado dentro de la aplicación, usaremos este token mientras configuramos nuestra protección de autenticación. ¿Qué es un guardia de autenticación? Protege el panel contra usuarios no autenticados que acceden a él sin tokens.
Primero, ingresaremos a nuestro archivo de ruta e importaremos la tienda. La tienda se importa debido al token que determinará el estado de inicio de sesión del usuario.
import store from './store.js'
Luego, dentro de nuestra matriz de rutas, vaya a la ruta del panel y agregue el método beforeEnter
que toma tres parámetros to
: from
y next
. Dentro de este método, simplemente decimos que si los tokens se almacenan (lo cual se hace automáticamente si se autentica), entonces next
, lo que significa que continúa con la ruta designada. De lo contrario, llevaremos al usuario no autenticado de regreso a la página de registro.
{ path: '/dashboard', component: DashboardPage, beforeEnter (to, from, next) { if (store.state.idToken) { next() } else { next('/signin') } }}
Creando el estado de la interfaz de usuario
En este punto, todavía podemos ver el panel en la navegación, ya sea que hayamos iniciado sesión o no, y eso no es lo que queremos. Tenemos que agregar otro método debajo de los captadores llamados ifAuthenticated
que verifica si el token dentro de nuestro estado es null
y luego actualiza los elementos de navegación en consecuencia.
getters: { user (state) { return state.user }, ifAuthenticated (state) { return state.idToken !== null }}
A continuación, abramos el componente del encabezado y creemos un método llamado auth
dentro de la computed
propiedad. Eso se envía a los ifAuthenticated
captadores que acabamos de crear en la tienda. ifAuthenticated
Regresará false
si no hay ningún token, lo que automáticamente significa que auth
también lo sería null
y viceversa. Después de eso, agregamos un v-if
para verificar si auth
es así null
o no, determinando si la opción del panel se mostrará en la navegación.
template header div router-link to="/"Vue Authenticate/router-link /div nav ul li v-if='auth' router-link to="/dashboard"Dashboard/router-link /li li v-if='!auth' router-link to="/signup"Register/router-link /li li v-if='!auth' router-link to="/signin"Log In/router-link /li /ul /nav /header/templatescript export default { computed: { auth () { return this.$store.getters.ifAuthenticated } }, }/script
Saliendo de tu cuenta
¿Qué es una aplicación sin botón de cierre de sesión? Creemos una nueva mutación llamada clearAuth
, que establece tanto el token como userId
en null
.
mutations: { authUser (state, userData) { state.idToken = userData.token state.userId = userData.userId }, clearAuth (state) { state.idToken = null state.userId = null }}
Luego, en nuestra logout
acción, nos comprometemos a clearAuth
eliminar el almacenamiento local y agregarlo router.replace('/')
para redirigir adecuadamente al usuario después de cerrar sesión.
Volver al componente del encabezado. Tenemos un onLogout
método que envía nuestra logout
acción en la tienda. Luego agregamos un @click
al botón que llama al onLogout
método como podemos ver a continuación:
template header div router-link to="/"Vue Authenticate/router-link /div nav ul li v-if='auth' router-link to="/dashboard"Dashboard/router-link /li li v-if='!auth' router-link to="/signup"Register/router-link /li li v-if='!auth' router-link to="/signin"Log In/router-link /li li v-if='auth' ul @click="onLogout"Log Out/ul /li /ul /nav /header/templatescript export default { computed: { auth () { return this.$store.getters.ifAuthenticated } }, methods: { onLogout() { this.$store.dispatch('logout') } } }/script
¿Ingreso automático? ¡Seguro!
Ya casi hemos terminado con nuestra aplicación. Podemos registrarnos, iniciar sesión y cerrar sesión con todos los cambios en la interfaz de usuario que acabamos de realizar. Pero, cuando actualizamos nuestra aplicación, perdemos los datos y cerramos la sesión, teniendo que comenzar todo de nuevo porque almacenamos nuestro token e ID en Vuex, que es JavaScript. Esto significa que todo el contenido de la aplicación se recarga en el navegador cuando se actualiza.
Lo que haremos es recuperar el token dentro de nuestro almacenamiento local. Al hacer esto, podemos tener el token del usuario en el navegador independientemente de cuándo actualicemos la ventana, e incluso iniciar sesión automáticamente siempre que el token siga siendo válido.
Cree un nuevo método de acciones llamado AutoLogin
, donde obtendremos el token y userId
del almacenamiento local, solo si el usuario tiene uno. Luego asignamos nuestros datos al authUser
método de las mutaciones.
actions : { AutoLogin ({commit}) { const token = localStorage.getItem('token') if (!token) { return } const userId = localStorage.getItem('userId') const token = localStorage.getItem('token') commit('authUser', { idToken: token, userId: userId }) }}
Luego vamos a nuestro App.vue
y creamos un created
método en el que enviaremos el autoLogin
desde nuestra tienda cuando se cargue la aplicación.
created () { this.$store.dispatch('AutoLogin')}
¡Hurra! Con esto, implementamos con éxito la autenticación dentro de nuestra aplicación y ahora podemos implementarla usando npm run build
. Vea la demostración en vivo para verlo en acción.
El sitio de ejemplo tiene únicamente fines de demostración. No comparta datos reales, como su correo electrónico y contraseña reales, mientras prueba la aplicación de demostración.
Deja un comentario