Skip to main content

3 posts tagged with "node"

View All Tags

· 7 min read
Jeffrey

一、Token

  • 什么是 Token? Token 指访问资源的凭据,是一种身份认证的方式,它是解决跨域认证的最流行的一种方式。

  • 为什么用 Token? 以前较为流行的是通过 session 去做身份认证,session 是通过服务器中保存会话数据来做身份认证,这种方式会导致在高并发中服务器压力过大的情况,还有就是,如果是服务器集群,那么就需要这些服务器 session 共享。

Token 不在服务器中保存会话数据,而是保存在客户端。每次请求的 headers 中存入 Token,在服务器中判断 Token 的有效性,是否可以访问资源。

  • 传统 Token 和 JWT 的区别

    • 传统 Token 用户发起登录请求,登录成功之后返回 Token,并且存于数据库,用户访问资源的时候需要携带 Token,服务端获取 Token 之后和数据库中的对比。
    • JWT 用户发起登录请求,登录成功之后返回 Token,但是不存于数据库,用户访问资源的时候需要携带 Token,服务端获取 Token 之后去校验 Token 的合法性。

二、JWT 实现过程

  • JWT 分为三个部分 header、payload、verify signature

  • header

内部包含有签名算法、Token 类型,然后通过 base64url 算法转成字符串

//明文例子:
{
"alg":"HS256",
"typ":"JWT"
}
  • payload 内部包含 JWT 标准数据和自定义数据,然后通过 base64url 算法转成字符串 JWT 标准数据常见的有:
iss:提供方。
sub:主题,一般是用户ID。
exp:过期时间。
iat:创建时间。
jti:token的唯一标识。

可选择性使用以上标准数据

//明文例子:
{
"id": 3,
"name": "Bmongo",
"age": 18,
"iat": 1588139323,
"exp": 1588139333
}

注意:由于 JWT 是默认不加密的,所以在这边不要存敏感信息

  • verify signature 这部分是对前两部分的签名,防止数据的篡改 secret 是服务器端保存的密钥,只有服务器端知道,再使用 header 中所指定的签名算法对上面的俩部分进行签名,按照以下公式生成签名
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)

复制代码 算出签名之后,把三部分通过.分隔开返回给用户就行了

  • 客户端请求

  • 每次客户端的请求都需要带上这个 token,一般是把 token 写入到请求的 headers 中

三、Node.js 中使用

Node.js 中使用 JWT

1.开始使用

通过 npm 包 jsonwebtoken 来完成 token 的生成和验证

npm install --save jsonwebtoken

2.生成、验证 Token

auth/token.js
const jwt = require('jsonwebtoken')
//撒盐,加密时候混淆
const secret = '113Bmongojsdalkfnxcvmas'

//生成token
//info也就是payload是需要存入token的信息
function createToken(info) {
let token = jwt.sign(info, secret, {
//Token有效时间 单位s
expiresIn: 60 * 60 * 10,
})
return token
}

//验证Token
function verifyToken(token) {
return new Promise((resolve, reject) => {
jwt.verify(token, secret, (error, result) => {
if (error) {
reject(error)
} else {
resolve(result)
}
})
})
}
const whiteList = ['/api/login']

function verifyTokenMiddle(req, res, next) {
if (!whiteList.includes(req.url)) {
// 发起请求是headers.authorization 添加token
verifyToken(req.headers.authorization)
.then((res) => {
next()
})
.catch((e) => {
res.status(401).send('invalid token')
})
} else {
next()
}
}

module.exports = {
verifyTokenMiddle,
createToken,
}

3.使用

app.js
var createError = require('http-errors')var express = require('express')var path = require('path')var cookieParser = require('cookie-parser')var logger = require('morgan')const { verifyTokenMiddle } = require('./auth/token')const expressSession = require('express-session')const redis = require('redis')const { redisConfig } = require('./config/config')// 创建Redis连接配置const redisClient = redis.createClient(redisConfig)const RedisStore = require('connect-redis')(expressSession)redisClient.on('connect', function () {  console.log('Redis client connected')})redisClient.on('error', function (e) {  console.error(e)})var app = express()app.use(express.static(path.join(__dirname, '/public')))//设置跨域访问 -- 开始 --app.all('*', function (req, res, next) {  res.header('Access-Control-Allow-Origin', '*') //的允许所有域名的端口请求(跨域解决)  res.header('Access-Control-Allow-Headers', 'Content-Type')  res.header('Access-Control-Allow-Methods', '*')  res.header('Content-Type', 'application/json;charset=utf-8')  if (req.method === 'OPTIONS') {    res.end()  } else {    next()  }})app.use(cookieParser())app.use(  expressSession({    store: new RedisStore({ client: redisClient }),    name: 'session_id', // 默认connect.sid    secret: 'yupi996', // 设置签名秘钥  内容可以任意填写    resave: true, // 强制保存,如果session没有被修改也要重新保存,默认true(推荐false)    saveUninitialized: true, // 如果原先没有session那么就设置,否则不设置(推荐true)    rolling: true, // 每次请求更新有效时长    cookie: {      domain: '.mianshiya.com',      // 全局设置cookie,就是访问随便api就会设置cookie,也可以在登录的路由下单独设置      maxAge: 1000 * 60 * 60 * 24 * 15, // 15 天后过期      httpOnly: true, // 是否允许客户端修改cookie,(默认true 不能被修改)    },  }))// app.use(logger('dev'));app.use(express.json())app.use(express.urlencoded({ extended: false }))// 添加验证token中间件app.use(verifyTokenMiddle)// 注册路由setRoutes()app.use(function (req, res, next) {  next(createError(404))})// error handlerapp.use(function (err, req, res, next) {  console.log(2)  // set locals, only providing error in development  res.locals.message = err.message  res.locals.error = req.app.get('env') === 'development' ? err : {}  // render the error page  res.status(err.status || 500)  res.send('error')})/** *  注册路由 */function setRoutes() {  const API = '/api/'  const fileDir = 'routes'  const noIncludePath = ['index']  const getPrefix = (path) => path.split('.')[0]  require('fs')    .readdirSync(path.join(__dirname, fileDir))    .filter((path) => noIncludePath.some((noPath) => !path.startsWith(noPath)))    .forEach((api) => {      app.use(        API + getPrefix(api),        require(path.join(__dirname, fileDir + '/') + getPrefix(api))      )    })}module.exports = app
routers/login
var express = require('express')
var router = express.Router()
const { createToken } = require('../auth/token')
router.get('/', function (req, res) {
var user = {
name: 'zs',
ps: 123,
}
let token = createToken(user)
res.send(token)
})
module.exports = router

总结

tip
  • 登录成功之后 服务端根据用户信息生成 token
  • 非登录接口发起请求是需设置 headers.authorization = token
  • 添加token验证中间件,除登录接口 其他接口全部验证 token
  • 验证成功通过,不成功提示错误 :::

· 3 min read
Jeffrey

n– 交互式管理您的 Node.js 版本

  • Node.js 版本管理:没有 subshel​​ls,没有配置文件设置,没有复杂的 API,只是简单的.

支持的平台

tip
  • n 在 macOS、Linux 上受支持,包括适用于 Linux 的 Windows 子系统和各种其他类 unix 系统。它是作为 BASH 脚本编写的,但不需要您使用 BASH 作为命令 shell。

  • n 不适用于 Microsoft Windows(如 PowerShell)或 Git for Windows BASH 或 Cygwin DLL 上的本机 shell。 :::

安装

  • 如果你已经安装了 Node.js,一个简单的安装方法 n 是使用 npm:
npm install -g n

第三方安装程序

brew install n
port install n
curl -L https://bit.ly/n-install | bash

安装 Node.js 版本

  • 只需执行 n version下载并安装一个版本的 Node.js。如果version已经下载,n 将从其缓存中安装。
n 10.16.0
  • n 自行执行以查看您下载的版本,并安装选定的版本。
$ n
node/4.9.1
ο node/8.11.3
node/10.15.0

指定 Node.js 版本

有多种方法可以为 n 命令指定目标 Node.js 版本。大多数命令使用最新的匹配版本,并 n ls-remote 列出多个匹配版本。 数字版本号可以是完整的或不完整的,带有可选的前导 v。

  • 4.9.1

  • 8: 8.xy 版本

  • v6.1: 6.1.x 版本 有两个特别有用的版本的标签:

  • lts: 最新的长期支持官方版本

  • latest, current: 最新官方发布

删除版本

删除一些缓存版本:

n rm 0.9.4 v0.10.0

删除除已安装版本之外的所有缓存版本:

n prune

保留 npm

Node.js 安装通常还包括 npm、 npx 和 corepack,但您可能希望使用以下方式保留当前(尤其是较新)版本--preserve:

$ npm install -g npm@latest
...
$ npm --version
6.13.7
# Node.js 8.17.0 includes (older) npm 6.13.4
$ n -p 8
installed : v8.17.0
$ npm --version
6.13.7

各种各样的

命令行帮助可以从n --help

· 2 min read
Jeffrey
  • PM2 是具有内置负载均衡器的 Node.js 应用程序的生产流程管理器。它允许您使应用程序永远保持活动状态,在不停机的情况下重新加载它们,并促进常见的系统管理任务。

1、pm2 需要全局安装

npm install -g pm2

2、进入项目根目录

2.1 启动进程/应用

pm2 start bin/www 或 pm2 start app.js

2.2 重命名进程/应用

pm2 start app.js --name wb123

2.3 添加进程/应用 watch

pm2 start bin/www --watch

2.4 结束进程/应用

pm2 stop www

2.5 结束所有进程/应用

pm2 stop all

2.6 删除进程/应用

pm2 delete www

2.7 删除所有进程/应用

pm2 delete all

2.8 列出所有进程/应用

pm2 list

2.9 查看某个进程/应用具体情况

pm2 describe www

2.10 查看进程/应用的资源消耗情况

pm2 monit

2.11 查看 pm2 的日志

pm2 logs

2.11.1 删除日志

pm2 flush

2.12 若要查看某个进程/应用的日志,使用

pm2 logs www

2.13 重新启动进程/应用

pm2 restart www

2.14 重新启动所有进程/应用

pm2 restart all

分布式部署(负载均衡)

1、增加多少工作线程

pm2 scale app +3

2、减少多少工作线程