Node express项目(1)JWT验证

1、安装依赖

pnpm i express-jwt // 解析jwt
pnpm i jsonwebtoken // 用于生成和解析token
pnpm i mysql
pnpm i express
pnpm i router

2、逻辑分析及功能代码

总共我们需要这五个文件,下面我依次介绍这五个地方 

首先一般数据库肯定需要连接池,那你肯定要对这部分做下处理

// pool.js

const mysql = require('mysql')
const util = require('./utils')
const pool = mysql.createPool({
  host: 'localhost', //数据库地址
    user: 'root', //用户
    password: 'xxx', //密码
    database: 'xxx', //库名
    port: 3306
})

let query = async (sql, values ) => {
   // to 函数是处理promise中返回格式的方法
  // 返回一个 Promise
  let poolPromise = await util.to(new Promise(( resolve, reject ) => {
    pool.getConnection(function(err, connection) {
      if (err) {
        reject( err )
      } else {
        connection.query(sql, values, ( err, rows) => {
          if ( err ) {
            reject( err )
          } else {
            resolve( rows )
          }
          // 结束会话
          connection.release()
        })
      }
    })
  }))
  return poolPromise
}

module.exports =  query

其次是我们的通用方法存放的地方

1、setToken :用来对数据进行加密的方法,返回值为token

2、verToken: 验证解析token的合理性

3、to: promise的格式处理返回

// utils.js

const query = require('./pool')
//用于生成和解析token
let jwt = require('jsonwebtoken');
let signkey = 'lin_da_da_yo';

/**
 *  查找一个帐号
 */
const findOne = async function (user) {
  [err, data] = await query(`SELECT * FROM login WHERE account = '${user.account}'`)
  if (err) {
    throw new Error(err)
  } else {
    return data
  }
}
exports.findOne = findOne

exports.setToken = function(username,password){
  return new Promise((resolve,reject)=>{
    const token = jwt.sign({
      name:username,
      _id:password
    },signkey,{ expiresIn:'1h' });
    resolve(token);
  })
}

exports.verToken = function(token){
  return new Promise((resolve,reject)=>{
    var info = jwt.verify(token.split(' ')[1],signkey);
    resolve(info);
  })
}

exports.to = function(promise, errorProps = {}, errorFirst = true) {
	return promise.then((data) => {
    return errorFirst ? [null, data] : [data, null]
  })
    .catch(err => {
      if(errorProps) Object.assign(err, errorProps)
      errorFirst ? [err, undefined] : [undefined, err]
    })
  }

 下面是请求的拦截及验证,如果你了解过axios,那么下面的逻辑就和axios拦截器类似

// connect.js

const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const vertoken = require('./utils')
const expressJwt = require('express-jwt');

app.all("*", function(req, res, next) {
    //设置允许跨域的域名,*代表允许任意域名跨域
    res.header("Access-Control-Allow-Origin", "*");
    //允许的header类型
    res.header("Access-Control-Allow-Headers", "content-type,Authorization");
    //跨域允许的请求方式
    res.header("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS");
    res.header("Content-Type", "application/json;charset=utf-8");
    if (req.method.toLowerCase() == 'options')
        res.send(200); //让options尝试请求快速结束
    else
        next();
})
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));


// 解析token获取用户信息
app.use(function(req, res, next) {
  var token = req.headers['Authorization'];
  if(token == undefined){
    return next();
  }else{
    vertoken.verToken(token).then((data)=> {
      req.data = data;
      return next();
    }).catch((error)=>{
      return next();
    })
  }
});
//验证token是否过期并规定哪些路由不用验证
app.use(expressJwt({
  secret: 'lin_da_da_yo',
  algorithms: ['HS256']
}).unless({
  path: ['/map/login']//除了这个地址,其他的URL都需要验证
}));
//当token失效返回提示信息
app.use(function(err, req, res, next) {
  if (err.status == 401) {
    return res.status(401).send({
      code: 0,
      msg: 'token失效'
    });
  }
});

exports.app = app

然后就是我们node项目的主文件,这里就是路由的模式,如果你写过vue或java等,应该是很熟悉这写法的

const { app } = require('./connect');

var map = require('./router/map')

app.use('/map', map)

app.listen(8001);

 3、业务代码(登录)

// /router/map.js

var express = require('express')
var router = express.Router()
const user = require('../utils')
const query = require('../pool')

//POST 登录
router.post('/login', (req, res) => {
 user.findOne(req.body) // 这一步,我是在sql中查找有无当前登录账号的用户
  .then(data => {
    return data
  })
  .then(data => {
    if (data.length > 0) {
      if (data[0].password == req.body.password) {
        return data[0]
      } else {
        throw new Error('登录失败,请检查密码是否正确')
      }
    } else {
      throw new Error('登录失败,请检查账号是否正确')
    }
  })
  // 获取动态路由菜单
  .then(async data =>  {
    const [err, rows] = await query(`SELECT * FROM 你的菜单表`)
    if (err) {
      throw new Error(err)
    } else {
      return {
        ...data,
        menu: rows
      }
    }
  })
  .then(data => {
    // 注入token
    user.setToken(data.account,data.password).then((token)=>{
      return res.send({ code: 2000, data: {
        ...data,
        token: token
      }})
    })
  })
  .catch(e => {
    res.send({
      code: 0,
      msg: e.message
    })
  })
})

4、项目注意点


4.1、express-jwt 依赖默认安装6.0.0后版本,需要在expressJwt实例化时多添加一个参数:algorithms: ['HS256']

4.2、本项目其实相对比较完善,里面也多用的是promise和async,await,用于解决连接池的回调抛出,大家有啥不懂的可以评论下提出喔~

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您提供一些指导和提示,但是我需要更多的信息来确保我的回答符合您的需求。 首先,您需要了解这些技术的基本概念和用法。以下是一些关键点: - Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时,可用于构建高性能的网络应用程序。 - ExpressNode.js 中最流行的 web 框架之一,它提供了一组强大的功能和工具,使得构建 web 应用程序变得更加容易。 - JWT(JSON Web Token)是一种基于 JSON 的开放标准,用于在网络应用程序之间安全地传输信息。JWT 包含加密的信息,可以被验证和信任。 - Angular 是一个流行的前端框架,用于构建单页应用程序。它使用 TypeScript 编写,并提供了一组强大的工具和组件来简化开发。 - MySQL 是一种流行的关系型数据库,常用于存储应用程序的数据。 现在,让我们来看看如何将这些技术组合在一起构建一个应用程序。 首先,您需要创建一个 Node.js 项目,并使用 Express 框架创建一个基本的 web 服务器。您可以使用以下命令创建一个新项目: ``` mkdir myapp cd myapp npm init ``` 然后,您可以使用以下命令安装 Express: ``` npm install express ``` 接下来,您需要创建一个 Express 应用程序,并配置路由和中间件。您可以使用以下代码创建一个基本的 Express 应用程序: ```javascript const express = require('express') const app = express() app.use(express.json()) app.get('/', (req, res) => { res.send('Hello, world!') }) app.listen(3000, () => { console.log('Server started on port 3000') }) ``` 这个应用程序使用 `express.json()` 中间件来解析请求体中的 JSON 数据,并定义了一个基本的路由,该路由将在根路径上返回一个简单的“Hello, world!”消息。 接下来,您需要配置身份验证和授权。您可以使用 JWT 来实现身份验证和授权。您可以使用以下代码生成和验证 JWT: ```javascript const jwt = require('jsonwebtoken') const secret = 'mysecret' function generateToken(user) { const payload = { id: user.id, name: user.name } const options = { expiresIn: '1h' } return jwt.sign(payload, secret, options) } function verifyToken(token) { return jwt.verify(token, secret) } ``` 这个代码定义了两个函数,一个用于生成 JWT,另一个用于验证 JWT。 接下来,您需要创建一个 MySQL 数据库,并使用 Node.js 的 mysql 模块连接到它。您可以使用以下代码连接到 MySQL 数据库: ```javascript const mysql = require('mysql') const connection = mysql.createConnection({ host: 'localhost', user: 'username', password: 'password', database: 'myapp' }) connection.connect((err) => { if (err) { console.error('Error connecting to database', err) } else { console.log('Connected to database') } }) ``` 这个代码使用 `mysql.createConnection()` 函数创建一个 MySQL 连接,并使用 `connection.connect()` 函数连接到数据库。 最后,您需要创建一个 Angular 应用程序,并使用它来调用您的 Express API。您可以使用以下代码创建一个基本的 Angular 应用程序: ``` ng new myapp cd myapp ng serve ``` 这个应用程序使用 Angular CLI 创建一个基本的 Angular 应用程序,并使用 `ng serve` 命令启动开发服务器。 接下来,您需要添加一个服务来调用您的 Express API。您可以使用以下代码创建一个基本的 Angular 服务: ```typescript import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Injectable({ providedIn: 'root' }) export class ApiService { private baseUrl = 'http://localhost:3000'; constructor(private http: HttpClient) { } public getHello() { return this.http.get(`${this.baseUrl}/hello`); } public login(credentials) { return this.http.post(`${this.baseUrl}/login`, credentials); } } ``` 这个代码定义了一个名为 `ApiService` 的 Angular 服务,它使用 `HttpClient` 模块来调用 Express API 中的端点。 现在,您可以在 Angular 组件中使用这个服务来调用 Express API。例如,以下代码演示了如何在 Angular 组件中调用 `ApiService.getHello()`: ```typescript import { Component } from '@angular/core'; import { ApiService } from './api.service'; @Component({ selector: 'app-root', template: ` <h1>{{ message }}</h1> ` }) export class AppComponent { public message: string; constructor(private apiService: ApiService) { } ngOnInit() { this.apiService.getHello().subscribe((response: any) => { this.message = response.message; }); } } ``` 这个代码定义了一个名为 `AppComponent` 的 Angular 组件,它使用 `ApiService` 来调用 Express API 中的 `/hello` 端点,并将响应的消息显示在页面上。 这只是一个简单的示例,您可以根据自己的需求进行更改和扩展。希望这可以帮助您开始构建您的应用程序!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值