一步一步学Vue(七)

  前言:我以后在文章最后再也不说我下篇博文要写什么,之前说的大家也可以忽略,如果你不忽略,会失望的?,不过说出去的话还是要表示一下的,简单介绍一下路由钩子:

  正如其名,vue-router 提供的导航钩子主要用来拦截导航,让它完成跳转或取消。有多种方式可以在路由导航发生时执行钩子:全局的, 单个路由级的, 或者组件级的。

  1、全局钩子

  使用 router.beforeEach 注册一个全局的 before 钩子:

var router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {
  // TODO:处理跳转逻辑
})

to: Route: 即将要进入的目标 路由对象

  from: Route: 当前导航正要离开的路由

  next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。

  2、局部钩子

  故名思意,单个路由项的配置钩子函数:

var router = new VueRouter({
  routes: [
    {
      path: '/about',
      component: AboutComponent,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})

  3、组件级钩子

  上篇中已经介绍了一个beforeRouteUpdate 用来解决路由改变但是组件重用的问题,除了这个钩子函数,还包含

  • beforeRouteEnter
  • eforeRouteLeave
var Compoent = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // 在渲染该组件的对应路由被确认前调用
  },
  beforeRouteUpdate (to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用,上篇文章已经使用过
  },
  beforeRouteLeave (to, from, next) {
    // 导航离开该组件的对应路由时调用
  }
}

  Ok,上文留的坑表示完了,以后会继续讲的,主要没有考虑好好的使用场景,就简单的介绍一下了,这一篇文字内容会比较多,虽然我不太喜欢文字,但是没办法,说的少了反而说不清楚,见谅见谅。下文正式开始本篇主要内容。

今天主要说一下前后端分离模式下的认证和授权,讲这个也只是心血来潮,大家也可以放松的看一下,一起讨论下方案,可以完善一下用于SPA解决方案。

  现在前后端分离模式盛行,如果不考虑SEO等影响,SPA不失为一种很好的方案,这里简单的列一下其与传统web开发区别:

  1、传统web开发,每次请求都是请求完整的html,而spa每次都是局部请求并且是Ajax的;

  2、传统web开发,数据和格式(data和html)是在服务器端拼接构建,直接返回到浏览器端直接渲染;而spa,则是请求html片段后请求数据,在客户端通过客户端模版引擎构建后渲染的;

  3、传统web开发,前后端不分离,好多时候前端工作内容就是静态页面,所有的业务逻辑都在服务端;前后端分离后,大大增加前端的比重,一定程度上减轻了服务端的负担,让前端有了大前端的概念,让前端升职加薪块了很多,这是挑战也是喜事儿,以后再也不会有人说前端是切页面的了;

4、spa开发模式,前后通过json交互,更加轻量级,后端接口对于前端来说就是数据服务;nodejs的出现,让前端开发更往后了一层,有了前端的服务端(也就是中间层)的概念。

  我在做前后端分离架构时,一般的思路是:nginx作为前端服务器,并负责请求转发(不加入node层,如果加入node层,可以直接去掉nginx),也就是兼反向代理服务器,后台通过rest接口提供服务;使用node或者nginx的好处是,可以很方便的处理跨域问题,如果不明白的,可百度或留言,今天网络不给力,很多node模块安装不了,只能以伪代码的方式讲思路了,大家见谅。

  对于需要授权的服务我们需要覆盖以下用例:

  1、用户未登录只能打开登录页面;

 2、用户登录信息有误,登录失败

  3、用户登录信息正确,服务端分配token,用于请求rest接口

  4、用户登录后请求资源,可正常返回;

  5、用户登录后token过期,请求rest接口资源,返回401;

  6、附带无效token请求资源,返回401

  针对上述用例,客户端设计时需要完成如下几个功能:

  1、注册vue路由钩子函数,beforeEnter,在每次路由跳转前,进行路由检查,判断token是否存在;如果不存在,则打开到login页面,如果存在,则可以执行路由next操作

  2、针对每次请求的ajax操作,拦截所有请求操作,加入token到http头;拦截所有响应操作,对401等特殊状态码进行处理或者跳转。

  客户端可能的伪代码如下:

var LoginComponent = {
    template: `
    
     <div class="login" >
        username:<input type="text" v-model="user.username" />
        password:<input type="password" v-model="user.password" />
        <input type="button" @click="login()" value="login" />
     </div>
    `,
    data: function () {
        return {
            user: {
                username: '',
                password: ''
            }
        }
    },
  //其它组件省略。。。

    methods: {
        /**
         * 登录后保存token到localStorage
         */
        login: function () {
            ajaxPost('/login', this.user).then(res => {
                localStorage.setItem('token', res.data.token);
                //保存后执行跳转,跳转到路由query中传递的地址
            }, err => console.log(err))
        }
    }
}

var router = new VueRouter({
    //TODO:各种路由定义;
    routes: [
        {
            name: 'login', path: '/loin', component: LoginComponent
        }
    ]
});

//注册全局事件钩子
router.beforeEnter(function (to, from, next) {
    if (!localStorage.getItem('token')) {
        next({
            path: '/login',
            query: { redirect: to.fullPath }
        })
    } else {
        next();//如果存在token、则继续前进
    }
});

服务端需要做的工作:

  1、判断是否是登录请求,如果是登录请求,不检查http header中的token;验证用户信息,如果验证通过,则创建token,设置过期时间并返回;如果验证不通过,则返回错误信息即可;

  2、在非登录请求的情况下(这里基于jwt生成token),获取http header中token,如果获取不到,则直接返回401,并提示token无效;获取token后,使用服务端密钥,对token进行解密,如果解密失败,则说明token无效,返回401;如果解密成功,则判断是否过期,如果已过期,则返回401,并提示token已过期。(jwt一般会使用「sub,exp,iat等字段;其中包含了主题部分,创建时间戳等各种,可以满足绝大多数场景」)

  服务端可能的伪代码如下(基于Express 4.x):

var express = require("express");

var app = express();

//鉴权中间件
app.use(function (req, res, next) {
    if (req.path === '/login') {
        //TODO:进行登录验证,并响应token
        res.json({
            success: true,
            data: {
                token: 'xxxxxx'
            }
        })
    } else {
        var token = req.headers['Authorization'];
        //TODO:判断请求是否合法
        //如果不合法,这里直接返回401 ,并提示信息
        if (!valid(token)) {
            res.status(401)
        } else {
            //如果合法 执行next操作
            next();
        }

    }
});

//其它路由服务
//app.get('xxxx')
//...其它路由服务

app.listen(80,function(){
    console.log("port 80 is listenning!!!");
})

  上面的代码经过完善后是可以运行的,今天时间比较仓促,就写这么多吧,虽然我不准备说一下篇的内容是什么,但是下一篇至少要完成这个认证的demo的,对于node平台的基础知识希望读者有一个简单的了解,这样对后台的处理也会有帮助。

  ps:今天家里网络超级慢,下载一个express模块近三个小时,重试了好几次,还是不行,放弃了。下雨网络也慢,服了。。。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java帮帮-微信公众号-技术文章全总结

Python常见面试题【悟空教程】

1.MySQL 数据库总结 MySQL 可以建多少个数据库,理论上是没有限制的,每一个数据库可以有上亿的对象,但是一般基于硬件要求、效率问题一般不超过64个, ...

1292
来自专栏Java架构

前沪江高级架构师学习笔记分享:分布式框架设计与实现

1906
来自专栏智能算法

Python学习(九)---- python中的线程

原文地址: https://blog.csdn.net/fgf00/article/details/52773459 编辑:智能算法,欢迎关注! 上期我们一起学...

1382
来自专栏大内老A

谈谈基于OAuth 2.0的第三方认证 [中篇]

虽然我们在《上篇》分别讨论了4种预定义的Authorization Grant类型以及它们各自的适用场景的获取Access Token的方式,我想很多之前没有接...

2246
来自专栏点滴积累

geotrellis使用(二)geotrellis-chatta-demo以及geotrellis框架数据读取方式初探

在上篇博客(geotrellis使用初探)中简单介绍了geotrellis-chatta-demo的大致工作流程,但是有一个重要的问题就是此demo如何调取数据...

4116
来自专栏和蔼的张星的图像处理专栏

1.Win10+VsCode的C/CPP编译环境搭建

我是从开始学C++的时候就一直用的是visual studio,毕竟宇宙第一IDE,写和调试都是超级方便快捷,唯一的缺点可能就是启动慢一点。 之前电脑没有换固...

4966
来自专栏更流畅、简洁的软件开发方式

ajax的再次封装!

js的动态加载、缓存、更新以及复用 系列有点卡文,放心会继续的。先来点更基础的,为js的加载做点铺垫。   jQuery的ajax本来就很方便了,为啥还要在进一...

2358
来自专栏零基础使用Django2.0.1打造在线教育网站

零基础使用Django2.0.1打造在线教育网站(五):简易留言簿交互实现

努力与运动兼备~有任何问题可以加我好友或者关注微信公众号,欢迎交流,我们一起进步!

3868
来自专栏安恒信息

干货分享 | GoAhead服务器 远程命令执行漏洞(CVE-2017-17562) 分析报告

安全通告 1 GoAhead Web Server是为嵌入式实时操作系统(RTOS)量身定制的开源Web服务器。很多国际一线大厂商,包括IBM、HP、Oracl...

30112
来自专栏代码世界

Python之进程

进程 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机...

4927

扫码关注云+社区