5 登录验证及权限设置

既然要做一个系统,肯定就少不了登录验证,我们先实现一个简单的登录页面。首先在components文件夹下新建一个Login.vue文件。

页面相关

首先是html和css部分,script稍后再做介绍。

<template>
  <div class="base-background">
    <div class="outer">
      <div class="login-box">
        <el-form :label-position="labelPosition" label-width="auto">
          <el-form-item label>
            <el-input v-model="username" clearable>
              <template slot="prepend">账号</template>
            </el-input>
          </el-form-item>
          <el-form-item label>
            <center>
              <el-input v-model="password" show-password clearable>
                <template slot="prepend">密码</template>
              </el-input>
            </center>
          </el-form-item>
          <center>
            <el-button class="primary" round @click="login">登录</el-button>
          </center>
        </el-form>
      </div>
    </div>
  </div>
</template>
<style scoped>
.base-background {
  position: absolute;
  height: 100%;
  width: 100%;
  background-color: rgb(165, 219, 245);
}
.outer {
  border: 1px;
  width: 400px;
  height: 300px;
  margin: auto;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: transparent;
}
.login-box {
  text-align: center;
  vertical-align: middle;
  margin-top: 80px;
  height: 100%;
  width: 100%;
}
</style>

由于自己还没有系统的学习css,所以比较丑= =。然后在路由中添加相关信息(和根路由'/'同级):

{
      path: '/Login',
      name:'login',
      component:() =>import('@/components/Login.vue')
    }

直接访问 http://localhost:8080/Login ,效果如下:

8b7c1b79404cee3adf7eae065caf5d81.png

现在要做的就是将用户名和密码传输到后端,通过服务器进行验证,这个过程中会使用到axios。

axios

axios是一个易用、简洁且高效的http库,简单理解为一款发送http请求的工具即可。

首先进行安装:

npm install axios

然后在main.ts中引入:

import axios from 'axios'

然后再添加相应的配置:

axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'
// 为get和post方法分别添加头信息
axios.defaults.headers.get['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'
axios.defaults.withCredentials = true
// 需要访问的api的ip地址
axios.defaults.baseURL = 'http://192.168.32.42:8000'

// 设置请求时的拦截器,即在请求前在Authorization字段中写入token
axios.interceptors.request.use(
  config => {
    if (sessionStorage.token) {
      config.headers.Authorization = `${sessionStorage.token}`;
    }
    return config;
  },
  err => {
    return Promise.reject(err);
  }
)


// 设置响应时的拦截器,如果http状态码是401或者404则说明请求异常,清空token并返回到登录页面
axios.interceptors.response.use(
  response => {
    return response;
  },
  error => {
    if (error.response) {
      switch (error.response.status) {
        case 401:
          sessionStorage.token = "";
          router.replace({
            path: '/Login',
            query: { redirect: router.currentRoute.fullPath }
          });
          break;
        case 404:
          sessionStorage.token = "";
          router.replace({
            path: '/Login',
            query: { redirect: router.currentRoute.fullPath }
          });
          break;
      }
    }
    return Promise.reject(error.response)
  }
);

然后将axios注册为全局变量(该语句一定要用在实例化Vue后边):

Vue.prototype.$http = axios

我们再考虑一下Login.vue组件中的登录逻辑,主要逻辑如下所示,对应的注释也给了出来:

<script>
import qs from 'qs';
export default {
  data() {
  // 一些数据的初始化
    return {
      labelPosition: "center",
      username: "",
      password: ""
    };
  },
  methods: {
    login() {
      let url = "/api/login";
      // 访问对应的后端的api获取登录信息
      this.$http.post(
        url,
        qs.stringify({ user: this.username, password: this.password })
      ).then(response => {
          console.log(response.data.token);
          // 将获取的数据给予相应的字段,主要是用户名,权限和认证token
          sessionStorage.token = response.data.token;
          sessionStorage.level = response.data.level;
          sessionStorage.user = response.data.username;
          console.log(sessionStorage.user)
          // 登录成功则跳转到根路由处
          this.$router.push('/')
      }).catch((err) => {
          console.log('登录失败!!!')
          this.$message.error('登录失败!!!');
      });
    }
  }
}
</script>

这里看到还需要一个qs模块,我们安装即可:

npm install qs

然后我们开启后端服务器(后端用的是python的flask框架,有机会会详细介绍),输入账号密码,这个账号密码当然是你自己注册并存放在数据库中的。进行登录测试:

daa368d4e1d2c62b742baff4ef01a8a3.gif

至此我们就成功的完成了一个登陆模块。

权限设置

开发过程中肯定也要考虑安全问题,比如有的页面需要对应的用户权限才能访问,没有登录则无法访问。

在vue中可以通过在路由元信息中添加认证设置,从而实现权限控制。

比如我们在/2的路由下的元信息中添加认证字段:

{
  path: '2',
  name: '2',
  // 懒加载
  component: () => import('@/components/Content.vue'),
  meta: {
    title: '2',
    requireAuth: true
  }
}

当然,要使权限设置生效,我们还需要添加一个路由守卫,在每次路由跳转前验证该页面是否需要验证,将如下的代码添加至router.ts中:

router.beforeEach((to, from, next) => {
  let token = sessionStorage.token;//从sessionstorage中获取,或者利用localstorage和vuex
  let level = sessionStorage.level;
  if (to.meta.requireAuth) { //如果该路由需要登录
    if (token) {  //且token是存在的,则可以进入该路由
      next()
    } else {
      next({
        path: '/Login', //否则跳转到登录页面,
        query: { redirect: to.fullPath }//将跳转的路由path作为参数,登录成功后跳转到该路由
      })
    }
  } else {
    next()
  }
});

然后我们来进行测试,看看效果如何:

836ae372ce8ee94eb8df671abb52ebdb.gif

不登录直接访问根路由是可以的,因为我们没有添加认证设置。我们再来看看访问/2的效果:

944b3b5dd9fb2f1ab7f332e4d50ef25b.gif

看到跳转到了登录页面,因为我们访问的时候没有token,所以无法访问。因此在进行权限设置时只需要为相应的页面添加认证设置即可。

多页面共享SessionStorage

在实际使用过程中有这么一个使用场景,用户访问一个网站时要打开多个标签页。这个时候问题就来了,我们肯定不能让用户多次登录啊,可通过设置共享SessionStorage来实现。具体SessionStorage,localStorage,Cookie的区别可参考:https://jerryzou.com/posts/cookie-and-web-storage/

下面直接上实现方法,在router.ts中添加如下代码:

(function () {

  if (!sessionStorage.length) {
    // 这个调用能触发目标事件,从而达到共享数据的目的
    localStorage.setItem('getSessionStorage', Date.now().toString());
  }

  // 该事件是核心
  window.addEventListener('storage', function (event) {
    if (event.key == 'getSessionStorage') {
      // 已存在的标签页会收到这个事件
      localStorage.setItem('sessionStorage', JSON.stringify(sessionStorage));
      localStorage.removeItem('sessionStorage');

    } else if (event.key == 'sessionStorage' && !sessionStorage.length) {
      // 新开启的标签页会收到这个事件
      if (event.newValue) {
        var data = JSON.parse(event.newValue),
          value;
        for (var key in data) {
          sessionStorage.setItem(key, data[key]);
        }
      }
    }
  });
})();

同样地,我们来看看实际效果。首先先进行登录操作,为了保证我们处于登录状态,我们访问/2路由:

055f328ce4348f8fbb21e07d3c23ccfa.png

然后我们再打开一个新的标签页,不进行登录操作,看看是否能直接访问/2:

f1de4d798d28efad8313bbaf23b62d68.gif

这说明SessionStorage共享成功。

登录模块就先介绍到这里,后边会带来其他的介绍。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐