Esquema de autenticación de front-end bajo la separación de front-end y back-end del proyecto Vue
###?Pila de tecnología
Depósito de la familia Vue de front-end, en segundo plano. neto.
###?Análisis de requisitos
1.? Autenticación de enrutamiento front-end, bloqueo de intrusiones en la barra de direcciones
2.? Los datos de enrutamiento se administran en segundo plano y el front-end solo carga rutas de forma asincrónica de acuerdo con reglas fijas.
3.? El control de permisos es preciso para cada botón.
4.? ¿Renovar token automáticamente
5.? Sólo se puede iniciar sesión con una cuenta en el mismo navegador.
###?Solución front-end
gt? Para los requisitos 1, 2 y 3, se utiliza un esquema de enrutamiento de carga asíncrono.
1.? Primero, escriba la protección de enrutamiento global de vue.
2.? Excluya rutas de inicio de sesión y rutas no autenticadas.
3.? Solicitud para extraer datos del menú del usuario después de iniciar sesión.
4.? Menú de procesamiento y datos de coincidencia de rutas en vuex
5.? Envíe de forma asincrónica los datos de ruta procesados en vuex a la ruta a través de addRoutes'.
```
router.beforeEach((to,?from,?next)?= gt?{
//?Determinar si el usuario actual Extrajo el menú de permisos
If? (store . state . sidebar . user router . length? ===?0)?{
//?Extrae cuando no hay menú.
getMenuRouter()
Entonces (res?= gt?{
let?_menu?=?res.data.Data.ColumnDataList?||? [];
//?If? (RES . datos . datos . lista de datos de columnas . longitud? gt? 0)?{
//?Organizar los datos de enrutamiento<; /p>
store.commit("setMenuRouter ", _ menu);
//?Lista de entrega de permisos de inserción
router agregar rutas(store . state . sidebar . enrutador de usuario);
Siguiente ({...a,? Reemplazar:? ¿En serio?});
//?}
} ) p>
.catch(eh?= gt?{
//?console.log(err);
//?Message.error("Error en la conexión del servidor" );
});
}? De lo contrario, {
//Cuando hay permiso del usuario, ¿se han generado todas las rutas accesibles? menú sin permiso, será dirigido automáticamente a una página 404.
¿Y si? (a.ruta?==?"/iniciar sesión ")? {
Siguiente({
Nombre:? "Índice"
});
} ¿De lo contrario? {
siguiente();
}
}
} ¿De lo contrario? {
//?¿Redireccionar para iniciar sesión cuando no hay estado de inicio de sesión? O una ruta para ingresar al estado sin inicio de sesión
¿Y si? (¿a.path?==?"/Login"?||?to.meta.auth?===?0)?{
siguiente();
}? ¿De lo contrario? {
Siguiente({
Ruta:? "/Iniciar sesión"
});
}
}
});
```
#####?Atención
gt? La ruta sin autenticación que tengo aquí está escrita directamente en index.js en la carpeta del enrutador y lleva el identificador especificado a través de la metainformación de enrutamiento.
```
{
Ruta:? "/err-404 ",
Nombre:? "Error 404",
meta:? {
? Proceso de dar un título:? Incorrecto
},
Componente:? ¿Resolver? =gt? Solicitud(["../views/error/404.vue"],? Resolver)
},
```
gt? Todas las rutas mencionadas anteriormente se generan de acuerdo con ciertas reglas basadas en los datos del menú devueltos por el fondo, por lo que algunas rutas que no son menús y requieren estado de inicio de sesión se escriben en router.js en la carpeta del enrutador. Al procesar los datos del menú devueltos por el fondo en el paso 4 anterior, envíelos junto con los datos de enrutamiento del menú procesados a través de addRoutes. ?
Hacer esto tendrá un cierto riesgo de ser invadido por la barra de direcciones, pero la mayor parte del enrutamiento aquí no es muy importante. Si quiere toser, puede configurar un diccionario para que coopere con la interfaz en segundo plano para cargar con precisión cada ruta.
```
//?Únete a la empresa
{
Ruta:? "/Unirse a la empresa",
Nombre:? "Unirse a la empresa",
Componente:? ¿Resolver? = gt? Solicitud([`@/views/index/join-company . vue `],? ¿Resolver)?
},
```
¿gt? En Vuex, los datos del menú asignados se convierten en datos de enrutamiento utilizables por el front-end. Esto es lo que hice:
Al agregar un menú, el sistema de gestión debe completar el campo de dirección de la página "Url". Una vez que la interfaz obtiene los datos del menú de fondo, coincide con la ruta del archivo cargado por la ruta según el campo 'Url'. La ventaja de tener una carpeta para cada menú es que los componentes js, css y privados de este menú se pueden dividir aquí.
```
menu.forEach(item?= gt?{
Let?routerItem?=?{
Ruta: ?Proyecto.
Nombre: ?Proyecto.
Meta: ?p>}, ?//?Los parámetros que se pueden llevar al definir una ruta se pueden utilizar para gestionar el funcionamiento del botón. permisos de cada ruta:? = gt
Requisitos([`@/views${item.
URL}/index.vue`],? resolver)? ///?Ruta real de la hoja de ruta
};
cuadro del enrutador push(elemento de ruta);
});
` `. `
gt? Lo que hago es cómo controlar con precisión cada botón. Pongo el código del botón en la metainformación de ruta, lo hago coincidir con la ruta actual y controlo si se crea el botón en la página.
Los datos del menú devuelven una estructura de varios niveles. El subconjunto debajo de cada menú es una matriz de códigos de permiso de botón debajo del menú actual. Puse los botones debajo de cada menú en la metainformación de enrutamiento meta.auth de este menú. La ventaja de esto es que la verificación de permisos del botón solo necesita coincidir con los datos en cada metainformación de enrutamiento del menú, por lo que la longitud del grupo de verificación generalmente no excede 5.
```
¿Creado()? {
¿Es este el dueño? =?Esto. $route.meta.auth.map(item?= gt?item.code);
}
Método:? {
¿Coincide con el propietario (autenticación)? {
¿Volver? this.owner.some(item?= gt?item?===?auth);
}
}
```
gt? La demanda 4 actualiza automáticamente el token. Este es un juicio de tiempo simple: agrega un campo al encabezado de la solicitud, notifica al fondo para actualizar el token y lo devuelve en el encabezado. Cuando la interfaz recibe una solicitud con un token, actualiza el token directamente.
```
//?En el interceptor de solicitudes de axios
¿Dejar? ¿simbólico? =?getSession(auth _ code);
¿Si? (simbólico)? config.headers.auth? =?token
Si? (tokenIsExpire(token))? {
//? Determine si es necesario actualizar jwt.
config.headers.refreshtoken? =?True;
}
//?En el interceptor de respuesta de axios.
¿Y si? (res.headers.auth)? {
setSession(auth_code, RES . encabezados . auth
}
```
gt? Cumplir con el requisito 5 es engorroso. Solo puede usar 'cookie' o 'local' para recorrer pestañas, por lo que no permito 'cookie' aquí, así que uso 'almacenamiento local'. Lea los datos del 'token' en el 'almacenamiento local' a través de la nueva página abierta y sincronice la información de la cuenta de varias páginas. El "jwt" utilizado por el "token" está cifrado con md5 en la interfaz.
Una cosa a tener en cuenta aquí es que la información de la cuenta debe sincronizarse inmediatamente al cambiar de página.
¿gt? Después de la transformación del requisito 5, la protección de enrutamiento global se ve así:
```
¿Función? _AUTH_()? {
//? Compruebe si la cuenta ha cambiado al cambiar de ventana.
ventana . addevent listener(" cambio de visibilidad ", función()?{
let?Local_auth?=?getLocal(auth_code, true);
let ?Session_auth?=?getSession(auth_code);
If?(document.hidden?==?false?amp amp?Local_auth?!=?Session_auth)? /p>
setSession(auth_code, Local_auth,? verdadero);
router.go(0)
}
})
router.beforeEach((a, ?from,?next)?= gt?{
//?Determine si el usuario actual ha accedido al menú de permisos.
Si ? (store . state . sidebar . user router . length?===?0)?{
//?Extraer cuando no haya menú
getMenuRouter()
. gt?{
let?_menu?=?res.data.Data.ColumnDataList?||?[];
//?if ? (RES . datos . datos . columna lista de datos . ¿gt? 0)?{
//?Organizar el menú de datos
store.commit("setMenuRouter ", _ menu);
//?Lista de entrega de permisos de inserción
enrutador. agregar rutas (almacenamiento. estado. barra lateral. enrutador de usuario) Siguiente ({...a,?¿en serio?} );
//?})
gt? {
//?console.log(err);
/. /?Message.error("Error en la conexión del servidor");
}) ;
} ¿De lo contrario {
//Cuando hay permiso del usuario, ¿Se generan todas las rutas accesibles? Si ingresa al menú sin permiso, ingresará automáticamente a 404 páginas.
¿Y si? (a.ruta?==?"/iniciar sesión ")? {
Siguiente({
Nombre:? "Índice"
});
} ¿De lo contrario? {
siguiente();
}
}
} ¿De lo contrario? {
//?¿Redireccionar para iniciar sesión cuando no hay estado de inicio de sesión? O una ruta para ingresar al estado sin inicio de sesión
¿Y si? (to.path?==?"/Login"?||?to.meta.auth?===?0)?{
siguiente();
}? ¿De lo contrario? {
Siguiente({
Ruta:? "/Iniciar sesión"
});
}
}
});
}
```
gt? El interceptor de solicitudes axios modificado en el requisito 5 es así.
Debido a que IE no puede usar el cambio de visibilidad, probar otros atributos de Baidu no es válido, por lo que el proceso antes de enviar la solicitud es aproximadamente el siguiente:
```
¿Y si? (navegador IE)? {?
setLocal('_ie ',?Math.random()
Let?Local_auth?=?getLocal(auth_code, true);
Let? Session_auth? =?getSession(auth_code);
if?(Local_auth?amp?Local_auth?!=?Session_auth)?{
setSession(auth_code,Local_auth,?True );
router.go(0)
¿Volver?
}
}
` ``
gt? Hay un pequeño problema a tener en cuenta aquí: debido al uso de "local", cuando abre el navegador por primera vez, es posible que se le indique que el inicio de sesión ha caducado. Creo que todos aquí pueden encontrarlo. una solución que se adapta a sus necesidades
# # #Conclusión
Después de estos procesos simples y fáciles de usar, nace una solución de autenticación front-end que básicamente cumple con los requisitos.