前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >手把手搭建koa2后端服务器-登录认证

手把手搭建koa2后端服务器-登录认证

作者头像
星星在线
发布2022-04-27 16:15:27
5740
发布2022-04-27 16:15:27
举报

跨域认证

现在我们的开发方式都是采用前后端分离的方式,因此后端一般都只提供数据,这就造成前后端域名不同,存在跨域请求的问题,浏览器为了安全方面考虑,对跨域请求有限制。为了避免非同源请求的失败,我们需要采取跨域资源共享 CORS 来解决这个问题。

安装 koa2-cors

代码语言:javascript
复制
yarn add koa2-cors
yarn add -D @types/koa2-cors

配置跨域认证

代码语言:javascript
复制
// src/app.ts
import KoaCors from 'koa2-cors';

app.use(
  KoaCors({
    origin: '*', // 设置允许的域名,*表示允许任何域名使用
    allowMethods: ['*'], // 设置允许的请求方法,*表示允许任何请求方法
    allowHeaders: ['*'], // 设置允许的请求头,*表示允许任何请求头
    credentials: true, //是否允许发送Cookie
  }),
);

浏览器在发送跨域请求的时候,当第一次请求到此域名时,会先发送一个 Option 请求,这个请求的作用是询问服务器是否支持跨域请求,以及支持哪些跨域请求的参数。

  • origin:这里配置的事允许跨域的域名,即支持哪些域名访问本服务器。
  • allowMethods:允许的请求方法。
  • allowHeaders:支持的请求头信息,不支持的请求头会过滤掉。

以上三个选项是主要的跨域请求配置,我们在这里全部设置为*号,表示允许所有的参数及域名,防止开发过程中出现一些异常错误,但是在实际部署中,我们可以根据实际情况配置具体的数据。

密码加密

现在服务器存储密码的时候都需要采用加密存储,不能再使用明文了,除了几次大型网站的泄密问题以外,国家也严格规定不能进行明文存储。加密库我们使用bcryptjs ,因为它不需要依赖其他的库。

安装

代码语言:javascript
复制
yarn add bcryptjs
yarn add -D @types/bcryptjs

加密注册密码

对于密码的处理,我们以中间件的形势进行处理,不修改现有注册逻辑,而且也熟悉一下单路由中间件的使用。

创建中间件文件

代码语言:javascript
复制
// src/middlewares/passwordMiddleWare.ts

import { Context } from 'koa';
import bcryptjs from 'bcryptjs';

/**
 * @description 密码加密处理请求中间件
 * @param ctx
 * @param next
 */
const encryptPassword = async (ctx: Context, next: () => Promise<any>) => {
  const { password, confirm } = ctx.request.body;
  const salt = bcryptjs.genSaltSync(10);
  if (password) {
    ctx.request.body.password = bcryptjs.hashSync(password, salt);
  }

  if (confirm) {
    ctx.request.body.confirm = bcryptjs.hashSync(confirm, salt);
  }

  await next();
};

export default encryptPassword;

在中间件中,如果调用了 await next(),就是把请求传递下去,这样我们就可以在不同的中间件中处理逻辑,如果不调用await next(),那么请求就不会继续传递下去,也就是后面的处理逻辑不会走到。

在用户注册路由上使用

代码语言:javascript
复制
// src/controller/common/router.ts
import KoaRouter from 'koa-router';
import IndexController from './view';
import encryptPassword from '../../middlewares/passwordMiddleWare';

const router = new KoaRouter();

router.post('/register', encryptPassword, IndexController.register);

export default router;

从数据库中的记录可以看到,我们的密码加密已经生效了,而且我们没有修改注册逻辑里面的代码。

加密密码验证

密码加密后,我们怎么判断用户输入的密码是否正常呢?登录逻辑中我们增加以下处理

代码语言:javascript
复制
// src/controller/common/view.ts
import bcryptjs from 'bcryptjs';

class IndexController {
  async login(ctx: Context) {
    ......
    // 校验密码是否正确
    if (!bcryptjs.compareSync(data.password, user.password)) {
      response.error(ctx, '密码错误');
      return;
    }
  }
}

登录认证处理

登录认证是所有后端服务器必备的功能,今天我们就来为我们的框架添加一下统一的登录认证逻辑。我们采用 JWT 的方式实现登录认证。

安装库

代码语言:javascript
复制
yarn add jsonwebtoken
yarn add @types/jsonwebtoken

创建 JWT 处理模块

  • 增加 secret 配置
代码语言:javascript
复制
// .env
AUTH_SECRET=secret
代码语言:javascript
复制
// src/config/index.ts
secret: process.env.AUTH_SECRET || 'secret'
  • 实现 Token 的生成和解析接口
代码语言:javascript
复制
// src/utils/auth.ts
import jwt from 'jsonwebtoken';
import config from '../config';

/**
 *
 * @param payload 用户信息
 * @returns
 */
export const generateToken = (payload: any): string => {
  return jwt.sign(payload, config.secret, { expiresIn: '1d' });
};

/**
 *
 * @param token
 * @returns
 */
export const verifyToken = (token: string): Record<string, any> => {
  try {
    return { data: jwt.verify(token, config.secret), error: null };
  } catch (error) {
    return { data: {}, error };
  }
};

创建认证中间件

ctx.state作为中间件消息传递的载体,具体来说就是我们给 ctx.state 对象中添加的属性和值,在其他 ctx 参数中均可以获取到,这样当我们的认证接口通过 Token 认证后,我们就可以把用户信息添加到 ctx.state 中,这样在其他的处理接口中就可以通过 ctx.state.user 拿到当前登录的用户信息。

代码语言:javascript
复制
// src/middlewares/authMiddleWare.ts
import type { Context, Next } from 'koa';
import { verifyToken } from '../utils/auth';

/**
 * @description 登录认证中间件
 * @param ctx
 * @param next
 */
const authMiddleWare = async (ctx: Context, next: Next) => {
  const { authorization } = ctx.request.header;
  if (!authorization) {
    ctx.throw(401, '未登录');
  }

  const token = authorization.split(' ')[1];
  const { data, error } = verifyToken(token);
  if (!error) {
    ctx.state.user = data;
  } else {
    switch (error.name) {
      case 'TokenExpiredError':
        ctx.throw(401, '登录已过期');
        break;
      default:
        ctx.throw(400, 'Token错误');
        break;
    }
  }
  await next();
};

export default authMiddleWare;

使用中间件修饰路由

  • 增加一个用户管理模块
  • 增加获取用户接口
代码语言:javascript
复制
// src/controller/user/view.ts
import { Context } from 'koa';
import response from '../../utils/response';

class UserController {
  async getUser(ctx: Context) {
    const { user } = ctx.state;
    if (user) {
      response.success(ctx, ctx.state.user, '获取用户信息成功');
    } else {
      response.error(ctx, '用户未登录');
    }
  }
}

export default new UserController();
  • 增加用户信息获取路由
代码语言:javascript
复制
// src/controller/user/router.ts
import KoaRouter from 'koa-router';
import UserController from './view';
import authMiddleWare from '../../middlewares/authMiddleWare';

const router = new KoaRouter();

router.get('/getUser', authMiddleWare, UserController.getUser);

export default router;

任何需要登录认证的路由都可以添加 authMiddleWare,这样就可以实现登录认证。还有一种方式是使用 koa-jwt 库,通过全局注册中间件为所有的路由都添加登录认证,将不需要认证的路由添加到白名单中即可。按照一般的思路来讲,我们的网站应该默认全部需要登录认证,特殊路由处理一下即可,但是我觉得 koa-jwt 那种方式不够优雅,不如在注册路由的时候,为指定路由添加 authMiddleWare。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-04-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 python爬虫实战之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 安装 koa2-cors
  • 配置跨域认证
  • 安装
  • 加密注册密码
  • 创建中间件文件
  • 在用户注册路由上使用
  • 加密密码验证
  • 登录认证处理
  • 安装库
  • 创建 JWT 处理模块
  • 创建认证中间件
  • 使用中间件修饰路由
相关产品与服务
消息队列 TDMQ
消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档