从0到1 koa-node-vue全栈开发(第三章:介绍koa-router的使用及使用jwt进行登录验证)

349 阅读3分钟

在上一章节中, 我们已经学习了koa-router这个中间件, 那么这一章节, 我们将继续学习如何来使用koa-router, 如下:

使用 koa-router 定义路由

const Koa = require('koa');
const bodyparser = require('koa-bodyparser');
const app = new Koa();
const Router = require('koa-router');
const router = new Router();
// 注册中间件
app.use(bodyparser());

router.get('/', (ctx, next) => {
    const { response } = ctx;
    response.body = 'index page';
});
// 查
router.get('/home', async (ctx, next) => {
    const { response } = ctx;
    response.body = 'home page';
    await next();
});
// 提交
router.post('/list', (ctx, next) => {
    const { response } = ctx;
    response.body = {
        list: []
    };
});
// 更改
router.put('/list', (ctx, next) => {
    const { response } = ctx;
    response.body = {
        list: []
    };
});
// 删除
router.delete('/list', (ctx, next) => {
    const { response } = ctx;
    response.body = {
        list: []
    };
});
app.use(router.routes());
app.use(router.allowedMethods()); // 路由的异常处理
app.listen(3000, () => {
    console.log(`http://127.0.0.1:3000`);
});

通过上一章节我们介绍了koa-router的多个中间件机制, 和当前章节里面的koa-router的常用方法, 下面我将使用jsonwebtoken来实现token验证

使用 jsonwebtoken 来实现登录验证

注册

返回值

登录

const Koa = require('koa');
const bodyparser = require('koa-bodyparser');
// sign 用来生成token
// verify 用来解析token
const { sign, verify } = require('jsonwebtoken');
// 私钥
const PRIVATE_KEY = 'montage_fz';
const app = new Koa();
const Router = require('koa-router');
const router = new Router();
// 注册中间件
app.use(bodyparser());

// 注册页面
router.get('/', (ctx, next) => {
    const { response } = ctx;
    response.body = `
        <h1>注册</h1>
        <form action="/register" method="post">
            <div>用户名: <input type='text' name='username'></div>
            <div>密 码: <input type='text' name='password'></div>
            <button type="submit">提交</button>  
        </form>
    `;
});
// 注册
router.post('/register', async (ctx, next) => {
    const { request, response } = ctx;
    const { body } = request;
    try {
        const { username, password } = body;
        if (username && password) {
            // 过期时间为六十秒, 每次注册的时候, 会生成一个新的token, 在实际项目中, 是在每次登陆的时候, 生成一个新的token
            const token = sign({ username, password }, PRIVATE_KEY, {
                expiresIn: 60
            });
            response.body = {
                message: '注册成功',
                username,
                token
            };
        } else {
            response.body = '用户名和密码不能为空';
        }
    } catch (e) {
        response.body = e;
    }
});
// 将token的验证, 单独封装, 方便多地方调用
const verity = async (ctx, next) => {
    const { request, response } = ctx;
    const { query } = request;
    try {
        const { token, username, password } = query;
        if (token) {
            // 解析token
            const decodeToken = verify(token, PRIVATE_KEY);
            const { username: user, password: pass } = decodeToken;
            if (username === user && password === pass) {
                await next();
            } else {
                ctx.redirect('/');
            }
        } else {
            response.body = '请携带token';
        }
    } catch (e) {
        response.body = e;
    }
};
// 登录
router.get('/login', verity, async (ctx, next) => {
    const { request, response } = ctx;
    response.body = '登录成功';
});

app.use(router.routes());
app.use(router.allowedMethods()); // 路由的异常处理
app.listen(3000, () => {
    console.log(`http://127.0.0.1:3000`);
});

问题 : 为什么要使用 token?

在使用token之前, 我们都是采用cookie和session来进行验证, 验证的过程主要分为以下几个步骤:
1.服务端session是用户第一次访问应用时,服务器就会创建的对象,代表用户的一次会话过程,可以用来存放数据。服务器为每一个session都分配一个唯一的sessionId,以保证每个用户都有一个不同的session对象。
2.服务器在创建完session后,会把sessionId通过cookie返回给用户所在的浏览器,这样当用户第二次及以后向服务器发送请求的时候,就会通过cookie把sessionId传回给服务器,以便服务器能够根据sessionId找到与该用户对应的session对象。

token验证过程:
1.用户在浏览器中输入用户和密码,后台服务器通过加密或者其他逻辑,生成一个Token。
2.前端获取到Token,存储到cookie或者localStorage中,在接下来的请求中,将token通过url参数或者HTTP Header头部传入到服务器
3.服务器获取token值,通过查找数据库判断当前token是否有效

从上面不难看出, session是储存在内存上的,每个用户登录都会将session储存在服务器的内存中, 而token是存在客户端, 从而减少了服务端的压力, 在加上不同的服务端上的session是不同的, 所以不能进行共享, 而token也可以解决这个问题.