El proyecto vue almacena el token en la tienda (vuex) y localstorage


Lea atentamente, piense una y otra vez, ¡Xiaobai comenzará! Si tiene alguna pregunta, deje un mensaje❤

1. Preparación y ficha

1. Preparación
  • Comprender
    la introducción del token (sesión, cookie) Token: el token solicita con frecuencia datos del servidor en el lado del cliente, y el servidor consulta con frecuencia la base de datos en busca de nombres de usuario y contraseñas y los compara para determinar si los nombres de usuario y las contraseñas son correctos o no, y realiza las indicaciones correspondientes. En este contexto, Token nació.
    El token es una cadena de cadenas generada en el servidor que sirve como token para que el cliente lo solicite. Si la interfaz utiliza el nombre de usuario / contraseña para solicitar la autenticación del servidor, y la autenticación del servidor se realiza correctamente, el servidor devolverá el token a la interfaz. El front-end puede traer un token para probar su estado legal cada vez que lo solicite. Si este token es persistente en el servidor (por ejemplo, almacenado en una base de datos), entonces es un token de identidad permanente (a menos que se establezca un período de validez).

  • Ventajas de los
    tokens La aplicación administra completamente el token, por lo que puede evitar la política del mismo origen. El
    token puede evitar ataques CSRF. El
    token puede ser sin estado y se puede compartir entre varios servicios para
    reducir la presión sobre el servidor, reducir las consultas frecuentes a la base de datos y hacer que el servidor sea más robusto .

  • Instalar vuex
    cnpm install vuex --save

2. Introducción al uso de tokens

Cuando los extremos frontal y posterior están completamente separados, la idea general de implementar la verificación de tokens en el proyecto Vue es la siguiente:

1. Al iniciar sesión por primera vez, el front-end ajusta la interfaz de inicio de sesión del back-end y envía el nombre de usuario y la contraseña.

2. El backend recibe la solicitud, verifica el nombre de usuario y la contraseña y, si la verificación se realiza correctamente, devuelve un token al frontend.

3. La interfaz obtiene el token, almacena el token en localStorage y vuex, y salta a la página de enrutamiento.

4. Cada vez que la interfaz salta a la ruta, juzga si hay un token en localStroage, salta a la página de inicio de sesión si no hay ningún token y salta a la página de enrutamiento correspondiente.

5. Cada vez que se ajusta la interfaz de back-end, se debe agregar un token al encabezado de la solicitud

6. El backend juzga si hay un token en el encabezado de la solicitud. Si hay un token, obtendrá el token y lo verificará. Si la verificación tiene éxito, devolverá los datos. Si la verificación falla (por ejemplo, el token caduca), devolverá 401. Si no hay ningún token en el encabezado de la solicitud, también devolverá 401.

7. Si la interfaz recibe el código de estado 401, borre la información del token y vaya a la página de inicio de sesión
————————————————
Declaración de derechos de autor: Este artículo es el trabajo original del blogger de CSDN "sonámbulo_1992" El artículo cumple con el acuerdo de derechos de autor CC 4.0 BY-SA. Adjunte el enlace de la fuente original y esta declaración para su reimpresión.
Enlace original: https://blog.csdn.net/sleepwalker_1992/article/details/82974703


2. Crear almacenamiento, almacenar, solicitar

1. directorio src:

Inserte la descripción de la imagen aquí
Nota: La creación de almacenamiento es opcional, porque encapsulé localstorage (almacenamiento en caché) en storage.js (el resto de este artículo usa js que encapsulé);Crear tienda es necesario

2. Crear almacenamiento (opcional)
// 封装操作localstorage本地存储的方法  模块化

var storage = {
    
    
    set(key, value) {
    
    
        localStorage.setItem(key, JSON.stringify(value));
        // localStorage.key = value;
        // localStorage[key] = value;
    },
    get(key) {
    
    
        return JSON.parse(localStorage.getItem(key));
    },
    getForIndex(index) {
    
    
        return localStorage.key(index);
    },
    getKeys(){
    
    
        let items = this.getAll();
        let keys = [];
        for (let index=0;index<items.length;index++){
    
    
            keys.push(items[index].key);
        }
        return keys;
    },
    getLength() {
    
    
        return localStorage.length;
    },
    getSupport() {
    
    
        return (typeof (Storage) !== "undefined") ? true : false;
    },
    remove(key) {
    
    
        localStorage.removeItem(key);
    },
    removeAll() {
    
    
        localStorage.clear();
    },
    getAll() {
    
    
        let len = localStorage.length;  // 获取长度
        let arr = new Array(); // 定义数据集
        for (var i = 0; i < len; i++) {
    
    
            // 获取key 索引从0开始
            var getKey = localStorage.key(i);
            // 获取key对应的值
            var getVal = localStorage.getItem(getKey);
            // 放进数组
            arr[i] = {
    
    
                'key': getKey,
                'val': getVal,
            }
        }
        return arr;
    }
}

export default storage;
3. Crea una tienda

import Vue from 'vue'
import Vuex from 'vuex'
import storage from '@/model/storage'

Vue.use(Vuex);
// 用Vuex.Store对象用来记录token
const store = new Vuex.Store({
    
    

  state: {
    
    
    // 存储token
    // token: storage.get('token') ? storage.get('token') : '',
    token:"",
    userName:"" // 可选
  },

  actions: {
    
    
    // removeToken: () => {
    
    
      // context.commit('set_token')
    // }
  },

  // 计算属性
  mutations: {
    
    
    // 修改token,并将token存入localStorage
    set_token(state,token) {
    
    
      state.token = token;
      storage.set('token', token);
      console.log('store、localstorage保存token成功!');
    },
    del_token(state) {
    
    
      state.token = "";
      storage.remove("token");
    },
    // 可选
    setUserInfo(state, userName) {
    
    
      state.userName = userName;
    }
  }
});

export default store;
4. Crear solicitud
import axios from 'axios'
import store from '@/store'
import router from '@/router'

// create an axios instance
const service = axios.create({
    
    
    // index.js设置了代理(解决跨域) invoice = http://58.246.79.142:25005
    baseURL: "/invoice", // url = base url + request url
    timeout: 5000, // request timeout
   }

})

//添加请求拦截器,若token存在则在请求头中加token,不存在也继续请求
service.interceptors.request.use(
    config => {
    
    
        // 每次发送请求之前检测都vuex存有token,那么都要放在请求头发送给服务器,没有则不带token
        // Authorization是必须的
        if (store.state.token) {
    
    
            config.headers.Authorization = store.state.token;
        }
        return config;
    },
    error => {
    
    
        console.log("在request拦截器显示错误:", error.response)
        return Promise.reject(error);
    }
);

//respone拦截器
service.interceptors.response.use(
    response => {
    
    
        // 在status正确的情况下,code不正确则返回对应的错误信息(后台自定义为200是正确,并且将错误信息写在message),正确则返回响应
        return response.data.code == 200 ? response : Promise.reject(response.data.message);
    },
    error => {
    
     
        // 在status不正确的情况下,判别status状态码给出对应响应
        if (error.response) {
    
    
            console.log("在respone拦截器显示错误:", error.response)
            switch (error.response.status) {
    
    
                case 401:
                    //可能是token过期,清除它
                    // this.$store.commit("del_token"); 
                    store.commit("del_token");

                    router.replace({
    
     //跳转到登录页面
                        path: '/login',
                         // 将跳转的路由path作为参数,登录成功后跳转到该路由
                        query: {
    
     redirect: router.currentRoute.fullPath }
                    });
            }
        }
        return Promise.reject(error.response.data);
    }
);


export default service

3. Configure el proxy, encapsule el enrutador, configure la protección del enrutador e importe el enrutador y almacénelo en main.js

Uno, configura el proxy

Inserte la descripción de la imagen aquí

2. Encapsular el enrutador de enrutamiento y configurar la protección de enrutamiento
/* eslint-disable */
import Vue from 'vue'
import Router from 'vue-router'
import Main from '@/main/index'

import store from '@/store'
import storage from '@/model/storage'

Vue.use(Router)

const routes = [
  {
    
    
    path: '/',
    name: 'Main',
    redirect: '/login',
    // 某些页面规定必须登录后才能查看 ,可以在router中配置meta,将需要登录的requireAuth设为true,
    meta: {
    
    
      requireAuth: true,
    }
  },

  {
    
    
    path: '/login',
    component: () => import('@/views/login'),
  },

  {
    
    
    path: '/invoice',
    redirect: '/invoice',
    component: Main,
  },

    ]
  },
  {
    
    
    path: '*',
    component: Main
  }
]

const router = new Router({
    
     routes: routes })

// 设置路由守卫,在进页面之前,判断有token,才进入页面,否则返回登录页面
if (storage.get("token")) {
    
    
  store.commit("set_token", storage.get("token"));
}
router.beforeEach((to, from, next) => {
    
    
  // 判断要去的路由有没有requiresAuth
  // to.matched.some(r => r.meta.requireAuth) or to.meta.requiresAuth
  if (to.matched.some(r => r.meta.requireAuth)) {
    
    
    if (store.state.token) {
    
    
      next(); //有token,进行request请求,后台还会验证token
    } else {
    
    
      next({
    
    
        path: "/login",
        // 将刚刚要去的路由path(却无权限)作为参数,方便登录成功后直接跳转到该路由,这要进一步在登陆页面判断
        query: {
    
     redirect: to.fullPath }  
      });
    }
  } else {
    
    
    next(); //如果无需token,那么随它去吧
  }
});

export default router
3. Introduzca el enrutador y almacénelo en main.js
import Vue from 'vue'
import App from './App'
import router from './router'

import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css'
import store from '@/store'

// 兼容ie
// import 'babel-polyfill';

Vue.use(ElementUI);
Vue.config.productionTip = false
// 定义vue属性,就可以全局使用this.$store
Vue.prototype.$store = store;

new Vue({
    
    
  el: '#app',
  router:router,
  components: {
    
     App },
  template: '<App/>'
})

Cuarto, el uso real de la página de inicio de sesión.

Solo proporcione la función de ejemplo de envío de formulario y la dependencia js

import {
    
     postLogin } from "@/api/login";

submitForm(formName) {
    
    
      this.$refs[formName].validate(valid => {
    
    
        if (valid) {
    
    
          let that = this;
          // console.log('username',this.loginForm.username)
          // 通过校验规则后进入校验用户名密码是否正确
          // 没有后台接口可以自定义一个函数来模拟,替换postLogin
          postLogin(this.loginForm.username, this.loginForm.password)
            .then(res => {
    
    
              console.log(res);
              
               that.$store.commit("set_token", res.data.token);
               that.$store.commit("setUserInfo", res.data.account);

              this.$notify({
    
    
                title: "登录成功",
                type: "success",
                showClose: false,
                duration: 1000
              });
              setTimeout(() => {
    
    
                // 此时要判断/login后面的参数,若无参数,进入主页;
                this.$router.push("/index");
                // 若有参数则参数为未有权限的那个路由,跳转到那个路由
                // this.$router.push(***); -- 具体要自己在这实现
              }, 1000);
            })
            .catch(error => {
    
    
            // 错误分为 status-请求错误 和 code-账号密码错误
              this.$message.error(error);
              console.log(error);
            });
        } else {
    
    
        // 不符合前端校验
          this.$message.error('format error:'+error);
          console.log('format error:',error);
          return false;
        }
      });
    }

@ / Api / login del que depende lo anterior:

import request from '@/utils/request.js'  // 前面封装的request
// 在request中,设置了根路径/invoice,所以每一个请求都会自动在前面带上invoice;
// 由于在config中的index配置过了代理(监听)的路径也是/invoice,但凡遇到/invoice路径就会替换为target目标地址(后台接口根地址)
// 实现跨域,即不限于只能访问根路径为127.0.0.1下的地址
export function postLogin(account,password) {
    
    
    console.log(account,password)
    return request({
    
    
        url: '/login',
        method: 'post',
        params:{
    
    
        // 具体传参(键)要看后台要求
            account:account,
            password:password
        }
    })
}

Supongo que te gusta

Origin blog.csdn.net/GeniusXYT/article/details/104402757
Recomendado
Clasificación