关于javascript:jwt

8次阅读

共计 5262 个字符,预计需要花费 14 分钟才能阅读完成。

一、jwt

1.1、介绍

在之前的我的项目中,大部分网页是通过 session 来判断用户是否有权限来拜访个别网页的,然而如果是 SPA 我的项目的话,前后端拆散,客户申请的是前端,所以并不会保留数据到 session,那该怎么办呢?针对这一问题,能够应用 jwt 来解决!

JWT 也就是 JSON Web Token(JWT),是目前最风行的跨域身份验证解决方案。

JWT 的组成 :一个 JWT 实际上就是一个字符串,它由三局部组成: 头部 (Header)、 载荷 (Payload) 与签名(signature)。

生成一个加密后的字符串,发送给客户端,客户端保留在浏览器中 (cookie/localstorage/sessionstorage), 在客户端申请敏感数据时,须要必须让客户端在头像携带加密的字符串(token) 给服务器,服务器获取到 token 值后,进行解密,进行信息的比对,如果比对胜利则返回数据,不对则不返回数据。

1.2、jsonwebtoken

nodejs 中 jsonwebtoken 提供了一套(jwt)加密和解码的算法

  • 装置
npm i -S jsonwebtoken
npm i -S express cors mongoose
  • 加密解密
var token=require("jsonwebtoken");
// 加密 生成密钥 key
var key=token.sign(数据, 加密串);
// 解密 通过加密串将密钥解密还原
var source=token.verify(key, 加密串);
  • 加密
const router = require('express').Router()
const jwt = require('jsonwebtoken')
// 设置一个 jwt 加密和解密时须要的 key 值
const secretKey = 'afwefjwlefjlwjflewjjfew;jfwe;jfwe;jf;ejf;w'

// 登录胜利后,让放弃登录者的状态,以前计划应用 session, 然而当初咱们前后端拆散,应用 jwt

// 接口登录操作
router.post('/login', (req, res) => {let {username, password} = req.body
  res.send({
    code: 0,
    msg: 'ok',
    data: {
      // 加密
      token: jwt.sign({
        id: 1,
        username,
        // token 过期工夫 个别设置时长为 2 小时,有一些公司 1 天 1 周 1 个月
        // exp: Date.now() + 7200 * 1000}, secretKey)
    }
  })
})
  • 解密
router.get('/users', (req, res) => {const token = req.headers['token']
  res.send({
    code: 0,
    msg: 'ok',
    data: {
      id: 1,
      name: '张三',
      token: jwt.verify(token, secretKey)
    }
  })
})

module.exports = router;

二、接口编写

2.1、restfulapi

一种软件架构格调、设计格调,而不是规范,只是提供了一组设计准则和约束条件。
RestfulApi:面向资源

解决的问题

  • 升高开发的复杂性
  • 进步零碎可伸缩性

2.2、标准

①、协定:API 与用户的通信协议,总是应用 http 或 https 协定。
②、域名:应该尽量将 API 部署在专用域名之下,例:http://api.demo.com
③、版本:应该将 API 的版本号放入 URL,不便和直观,例 http://api.demo.com/v1
④、门路
在 RESTful 架构中,每个网址代表一种资源(resource),所以网址中不能有动词,只能有名词。例:https://api.example.com/v1/users
⑤、HTTP 动词
对于资源的具体操作类型,由 HTTP 动词示意

GET(SELECT):从服务器取出资源(一项或多项)。POST(CREATE):在服务器新建一个资源。PUT/patch(UPDATE):在服务器更新资源(客户端提供扭转后的残缺资源)。DELETE(DELETE):从服务器删除资源。例上面的形式来操作和获取数据
GET /zoos:列出所有动物园
GET /zoos/ID:获取某个指定动物园的信息
POST /zoos:新建一个动物园
PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全副信息)DELETE /zoos/ID:删除某个动物园

⑥、过滤信息
如果记录数量很多,服务器不可能都将它们返回给用户。API 应该提供参数,过滤返回后果。例:?limit=10:指定返回记录的数量
⑦、状态码
服务器向用户返回的状态码和提示信息,常见的有以下一些(方括号中是该状态码对应的 HTTP 动词)

200 OK - [GET]:服务器胜利返回用户申请的数据,该操作是幂等的(Idempotent)。201 CREATED - [POST/PUT/PATCH]:用户新建或批改数据胜利。202 Accepted - [*]:示意一个申请曾经进入后盾排队(异步工作)204 NO CONTENT - [DELETE]:用户删除数据胜利。400 INVALID REQUEST - [POST/PUT/PATCH]:用户收回的申请有谬误,服务器没有进行新建或批改数据的操作,该操作是幂等的。401 Unauthorized - [*]:示意用户没有权限(令牌、用户名、明码谬误)。403 Forbidden - [*] 示意用户失去受权(与 401 谬误绝对),然而拜访是被禁止的。404 NOT FOUND - [*]:用户收回的申请针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。406 Not Acceptable - [GET]:用户申请的格局不可得(比方用户申请 JSON 格局,然而只有 XML 格局)。410 Gone -[GET]:用户申请的资源被永恒删除,且不会再失去的。422 Unprocesable entity - [POST/PUT/PATCH] 当创立一个对象时,产生一个验证谬误。500 INTERNAL SERVER ERROR - [*]:服务器产生谬误,用户将无奈判断收回的申请是否胜利。

⑧、返回后果
针对不同操作,服务器向用户返回的后果应该合乎以下标准

GET /collection:返回资源对象的列表数组
GET /collection/resource:返回单个资源对象
POST /collection:返回新生成的资源对象
PUT /collection/resource:返回残缺的资源对象
DELETE /collection/resource:返回一个空文档

三、构建我的项目

3.2、前端我的项目构建

应用 webpack 来进行前端我的项目工程化构建

  • package.json
{
  "name": "project",
  "version": "1.0.0",
  "description": "","main":"index.js","scripts": {"serve":"webpack-dev-server","build":"webpack"},"keywords": [],"author":"",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.14.3",
    "@babel/preset-env": "^7.14.2",
    "art-template": "^4.13.2",
    "art-template-loader": "^1.4.3",
    "babel-loader": "^8.2.2",
    "clean-webpack-plugin": "^4.0.0-alpha.0",
    "copy-webpack-plugin": "^6.4.1",
    "core-js": "^3.13.0",
    "css-loader": "^5.2.6",
    "file-loader": "^6.2.0",
    "html-loader": "^1.3.2",
    "html-webpack-plugin": "^4.5.2",
    "style-loader": "^2.0.0",
    "ts-loader": "^6.2.2",
    "typescript": "^4.3.2",
    "url-loader": "^4.1.1",
    "webpack": "^4.46.0",
    "webpack-cli": "^3.3.12",
    "webpack-dev-server": "^3.11.2"
  },
  "dependencies": {"jquery": "^3.6.0"}
}
  • webpack.config.js
const path = require('path')
// webpack 插件,帮忙 webpack 打包生成时,创立一个 index.html 文件
const HtmlWebpackPlugin = require('html-webpack-plugin')
// 删除打包成的 dist 目录
const {CleanWebpackPlugin} = require('clean-webpack-plugin')
// 动态资源复制
const CopyPlugin = require('copy-webpack-plugin')

module.exports = {
  // 开启的模式,生产还是开发
  mode: 'development',
  // 开发工具配置 开发时配置 source-map 作用:代码出错了,能够帮咱们定位到 src 目录中程序
  devtool: 'source-map',
  // 指定入口文件
  // 字符串
  entry: './src/main.js',
  // 进口
  output: {
    // 打包生成的文件门路 相对地址
    path: path.resolve('dist'),
    // 打包生成后的主入口 js 文件
    filename: '[name].[hash:8].js'
  },
  resolve: {
    alias: {'@': path.resolve('src')
    },
    extensions: ['.js', '.json', '.art']
  },
  // 加载器
  module: {
    // 规定
    rules: [
      // 解决 css
      {
        // 正则匹配 loader 解析文件扩展名
        test: /\.css$/i,
        // loader 执行程序
        // 执行程序 写在一行:从右向左,写在多行:从下向上执行
        use: [
          "style-loader",
          "css-loader"
        ]
      },
      // 图片解决
      {test: /\.(png|jpeg|jpg|gif)$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
              // 图片小于 8kb,就会被 base64 解决
              limit: 1 * 1024,
              name: 'images/[name].[ext]',
              publicPath: '/'
            }
          }
        ]
      },
      // html 中图片解决
      {
        test: /\.html$/,
        loader: ['html-loader']
      },
      // js 兼容解决
      {
        test: /\.js$/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: [
                [
                  '@babel/preset-env',
                  {
                    // 按需加载
                    useBuiltIns: 'usage',
                    // 指定 core-js 版本
                    corejs: 3,
                    // 兼容性做到哪个版本的浏览器
                    targets: {chrome: '75'}
                  }
                ]
              ]
            }
          }
        ]
      },
      // 模板引擎解释
      {
        test: /\.art$/,
        use: ["art-template-loader"]
      }
    ]
  },
  // 插件
  plugins: [new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      // 模板
      template: path.resolve('public/index.html')
    }),
    // 复制动态资源 -- 间接复制不做任何解决
    new CopyPlugin({
      patterns: [
        {
          // 起源
          from: path.resolve('public/favicon.ico'),
          // 指标
          to: path.resolve('dist/favicon.ico')
        }
      ]
    })

  ],
  devServer: {
    port: 3000,
    // 显示编辑打包进度
    progress: true,
    // 宁静模式, 不显打包信息
    quiet: true,
    // 代理
    proxy: {
      '/api': {
        target: 'https://api.iynn.cn/film',
        changeOrigin: true,
        pathRewrite: {// '^/api': ''}
      }
    }
  }
}
  • tsconfig.json
{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs", 
    "strict": true
  }
}
  • 前端路由

应用一个第 3 方路由模块

SME Router 是仿照 express 的格调编写的,前端路由库。所以 api 跟 express 有点相似。

npm i -S sme-router
https://sme-fe.github.io/website-router/zh/basic.html

# 修复后的路由
npm i -S wucode-router

正文完
 0