导航菜单

  • 0.api
  • 0.Async
  • 0.module
  • 1.ES2015
  • 2.Promise
  • 3.Node
  • 4.NodeInstall
  • 5.REPL
  • 6.NodeCore
  • 7.module&NPM
  • 8.Encoding
  • 9.Buffer
  • 10.fs
  • 11.Stream-1
  • 11.Stream-2
  • 11.Stream-3
  • 11.Stream-4
  • 12-Network-2
  • 12.NetWork-3
  • 12.Network-1
  • 13.tcp
  • 14.http-1
  • 14.http-2
  • 15.compress
  • 16.crypto
  • 17.process
  • 18.yargs
  • 19.cache
  • 20.action
  • 21.https
  • 22.cookie
  • 23.session
  • 24.express-1
  • 24.express-2
  • 24.express-3
  • 24.express-4
  • 25.koa-1
  • 26.webpack-1-basic
  • 26.webpack-2-optimize
  • 26.webpack-3-file
  • 26.webpack-4.tapable
  • 26.webpack-5-AST
  • 26.webpack-6-sources
  • 26.webpack-7-loader
  • 26.webpack-8-plugin
  • 26.webpack-9-hand
  • 26.webpack-10-prepare
  • 28.redux
  • 28.redux-jwt-back
  • 28.redux-jwt-front
  • 29.mongodb-1
  • 29.mongodb-2
  • 29.mongodb-3
  • 29.mongodb-4
  • 29.mongodb-5
  • 29.mongodb-6
  • 30.cms-1-mysql
  • 30.cms-2-mysql
  • 30.cms-3-mysql
  • 30.cms-4-nunjucks
  • 30.cms-5-mock
  • 30.cms-6-egg
  • 30.cms-7-api
  • 30.cms-8-roadhog
  • 30.cms-9-yaml
  • 30.cms-10-umi
  • 30.cms-12-dva
  • 30.cms-13-dva-ant
  • 30.cms-14-front
  • 30.cms-15-deploy
  • 31.dva
  • 31.cms-13-dva-antdesign
  • 33.redis
  • 34.unittest
  • 35.jwt
  • 36.websocket-1
  • 36.websocket-2
  • 38.chat-api-1
  • 38.chat-api-2
  • 38.chat-3
  • 38.chat-api-3
  • 38.chat
  • 38.chat2
  • 38.chat2
  • 39.crawl-0
  • 39.crawl-1
  • 39.crawl-2
  • 40.deploy
  • 41.safe
  • 42.test
  • 43.nginx
  • 44.enzyme
  • 45.docker
  • 46.elastic
  • 47.oauth
  • 48.wxpay
  • index
  • 52.UML
  • 53.design
  • index
  • 54.linux
  • 57.ts
  • 56.react-ssr
  • 58.ts_react
  • 59.ketang
  • 59.ketang2
  • 61.1.devops-linux
  • 61.2.devops-vi
  • 61.3.devops-user
  • 61.4.devops-auth
  • 61.5.devops-shell
  • 61.6.devops-install
  • 61.7.devops-system
  • 61.8.devops-service
  • 61.9.devops-network
  • 61.10.devops-nginx
  • 61.11.devops-docker
  • 61.12.devops-jekins
  • 61.13.devops-groovy
  • 61.14.devops-php
  • 61.15.devops-java
  • 61.16.devops-node
  • 61.17.devops-k8s
  • 62.1.react-basic
  • 62.2.react-state
  • 62.3.react-high
  • 62.4.react-optimize
  • 62.5.react-hooks
  • 62.6.react-immutable
  • 62.7.react-mobx
  • 62.8.react-source
  • 63.1.redux
  • 63.2.redux-middleware
  • 63.3.redux-hooks
  • 63.4.redux-saga
  • 63.5.redux-saga-hand
  • 64.1.router
  • 64.2.router-connected
  • 65.1.typescript
  • 65.2.typescript
  • 65.3.typescript
  • 65.4.antd
  • 65.4.definition
  • 66-1.vue-base
  • 66-2.vue-component
  • 66-3.vue-cli3.0
  • 66-4.$message组件
  • 66-5.Form组件
  • 66-6.tree
  • 66-7.vue-router-apply
  • 66-8.axios-apply
  • 66-9.vuex-apply
  • 66-10.jwt-vue
  • 66-11.vue-ssr
  • 66-12.nuxt-apply
  • 66-13.pwa
  • 66-14.vue单元测试
  • 66-15.权限校验
  • 67-1-network
  • 68-2-wireshark
  • 7.npm2
  • 69-hooks
  • 70-deploy
  • 71-hmr
  • 72.deploy
  • 73.import
  • 74.mobile
  • 75.webpack-1.文件分析
  • 75.webpack-2.loader
  • 75.webpack-3.源码流程
  • 75.webpack-4.tapable
  • 75.webpack-5.prepare
  • 75.webpack-6.resolve
  • 75.webpack-7.loader
  • 75.webpack-8.module
  • 75.webpack-9.chunk
  • 75.webpack-10.asset
  • 75.webpack-11.实现
  • 76.react_optimize
  • 77.ts_ketang_back
  • 77.ts_ketang_front
  • 78.vue-domdiff
  • 79.grammar
  • 80.tree
  • 81.axios
  • 82.1.react
  • 82.2.react-high
  • 82.3.react-router
  • 82.4.redux
  • 82.5.redux_middleware
  • 82.6.connected
  • 82.7.saga
  • 82.8.dva
  • 82.8.dva-source
  • 82.9.roadhog
  • 82.10.umi
  • 82.11.antdesign
  • 82.12.ketang-front
  • 82.12.ketang-back
  • 83.upload
  • 84.graphql
  • 85.antpro
  • 86.1.uml
  • 86.2.design
  • 87.postcss
  • 88.react16-1
  • 89.nextjs
  • 90.react-test
  • 91.react-ts
  • 92.rbac
  • 93.tsnode
  • 94.1.JavaScript
  • 94.2.JavaScript
  • 94.3.MODULE
  • 94.4.EventLoop
  • 94.5.文件上传
  • 94.6.https
  • 94.7. nginx
  • 95.1. react
  • 95.2.react
  • 96.1.react16
  • 96.2.fiber
  • 96.3.fiber
  • 97.serverless
  • 98.websocket
  • 100.1.react-basic
  • 101.1.monitor
  • 101.2.monitor
  • 102.java
  • 103.1.webpack-usage
  • 103.2.webpack-bundle
  • 103.3.webpack-ast
  • 103.4.webpack-flow
  • 103.5.webpack-loader
  • 103.6.webpack-tapable
  • 103.7.webpack-plugin
  • 103.8.webpack-optimize1
  • 103.9.webpack-optimize2
  • 103.10.webpack-hand
  • 103.11.webpack-hmr
  • 103.11.webpack5
  • 103.13.splitChunks
  • 103.14.webpack-sourcemap
  • 103.15.webpack-compiler1
  • 103.15.webpack-compiler2
  • 103.16.rollup.1
  • 103.16.rollup.2
  • 103.16.rollup.3
  • 103.16.vite.basic
  • 103.16.vite.source
  • 103.16.vite.plugin
  • 103.16.vite.1
  • 103.16.vite.2
  • 103.17.polyfill
  • 104.1.binary
  • 104.2.binary
  • 105.skeleton
  • 106.1.react
  • 106.2.react_hooks
  • 106.3.react_router
  • 106.4.redux
  • 106.5.redux_middleware
  • 106.6.connected-react-router
  • 106.6.redux-first-history
  • 106.7.redux-saga
  • 106.8.dva
  • 106.9.umi
  • 106.10.ketang
  • 106.11.antdesign
  • 106.12.antpro
  • 106.13.router-6
  • 106.14.ssr
  • 106.15.nextjs
  • 106.16.1.cms
  • 106.16.2.cms
  • 106.16.3.cms
  • 106.16.4.cms
  • 106.16.mobx
  • 106.17.fomily
  • 107.fiber
  • 108.http
  • 109.1.webpack_usage
  • 109.2.webpack_source
  • 109.3.dll
  • 110.nest.js
  • 111.xstate
  • 112.Form
  • 113.redux-saga
  • 114.react+typescript
  • 115.immer
  • 116.pro5
  • 117.css-loader
  • 118.1.umi-core
  • 119.2.module-federation
  • 119.1.module-federation
  • 120.create-react-app
  • 121.react-scripts
  • 122.react-optimize
  • 123.jsx-runtime
  • 124.next.js
  • 125.1.linux
  • 125.2.linux-vi
  • 125.3.linux-user
  • 125.4.linux-auth
  • 125.5.linux-shell
  • 125.6.linux-install
  • 125.7.linux-system
  • 125.8.linux-service
  • 125.9.linux-network
  • 125.10.nginx
  • 125.11.docker
  • 125.12.ci
  • 125.13.k8s
  • 125.14.k8s
  • 125.15.k8s
  • 125.16.k8s
  • 126.11.react-1
  • 126.12.react-2
  • 126.12.react-3
  • 126.12.react-4
  • 126.12.react-5
  • 126.12.react-6
  • 126.12.react-7
  • 126.12.react-8
  • 127.frontend
  • 128.rollup
  • 129.px2rem-loader
  • 130.health
  • 131.hooks
  • 132.keepalive
  • 133.vue-cli
  • 134.react18
  • 134.2.react18
  • 134.3.react18
  • 135.function
  • 136.toolkit
  • 137.lerna
  • 138.create-vite
  • 139.cli
  • 140.antd
  • 141.react-dnd
  • 142.1.link
  • 143.1.gulp
  • 143.2.stream
  • 143.3.gulp
  • 144.1.closure
  • 144.2.v8
  • 144.3.gc
  • 145.react-router-v6
  • 146.browser
  • 147.lighthouse
  • 148.1.basic
  • 148.2.basic
  • 148.3.basic
  • 148.4.basic
  • 148.5.basic
  • 149.1.vite
  • 149.2.vite
  • 149.3.vite
  • 149.4.vite
  • 150.react-window
  • 151.react-query
  • 152.useRequest
  • 153.transition
  • 154.emotion
  • 155.1.formily
  • 155.2.formily
  • 155.3.formily
  • 155.3.1.mobx.usage
  • 155.3.2.mobx.source
  • 156.vue-loader
  • 103.11.mf
  • 157.1.react18
  • 158.umi4
  • 159.rxjs
  • 159.rxjs2
  • 160.bff
  • 161.zustand
  • 162.vscode
  • 163.emp
  • 164.cors
  • 1. Serverless是什么?
    • 1.1 Serverless是什么?
    • 1.2 云函数
  • 2. serverless framework
  • 3. Serverless Components
    • 3.1 云函数 SCF 组件
      • 3.1.1 serverless.yml
      • 3.1.2 src\index.js
      • 3.1.3 tencent-scf.env
      • 3.1.4 布署
    • 3.2 API 网关组件
      • 3.2.1 tencent-api\serverless.yml
      • 3.2.2 布署
    • 3.3 布署静态网站
      • 3.3.1 serverless.yml
      • 3.3.2 index.html
    • 3.4 布署express项目
      • 3.4.1 创建项目
      • 3.4.2 serverless.yml
      • 3.4.3 sls.js
    • 3.5 布署express+layer项目
      • 3.5.1 serverless.yml
      • 3.5.2 src\sls.js
    • 3.6 部署Vue+Express全栈应用
      • 3.6.1 serverless.yml
      • 3.6.2 api\package.json
      • 3.6.3 api\app.js
      • 3.6.4 生成前端项目
      • 3.6.5 src\App.vue
  • 2.RBAC
    • 2.1 示意图
    • 2.2 表设计
      • 2.2.1 用户表(user)
      • 2.2.2 角色表(role)
      • 2.2.3 权限表(permission)
      • 2.2.4 角色用户表(role_user)
      • 2.2.5 角色权限(role_permission)
      • 2.2.6 数据库脚本
  • 3.egg.js
    • 3.1. 初始化项目
    • 3.2. 添加模块
    • 3.3. config\plugin.js
    • 3.4. config\config.default.js
    • 3.5. model\user.js
    • 3.6. app\controller\home.js
    • 3.7. app\router.js
    • 3.8. app.js
  • 4. 前端项目
    • 4.1. 启动项目
    • 4.2 config\config.ts
    • 4.3 services\login.ts
    • 4.4 services\user.ts
    • 4.5 models\login.ts
    • 4.6 utils\request.ts

1. Serverless是什么? #

1.1 Serverless是什么? #

  • 无服务器架构几乎封装了所有底层资源管理和系统运维工作
  • 服务器布署、扩缩容、运维、监控报警交由云服务器厂商来做
  • 前端开发只关注业务,不需要关注服务器

serverless2

1.2 云函数 #

  • 函数服务

2. serverless framework #

  • Serverless Framework 是业界非常受欢迎的无服务器应用框架,开发者无需关心底层资源即可部署完整可用的 Serverless 应用架构
  • Serverless Framework 具有资源编排、自动伸缩、事件驱动等能力,覆盖编码、调试、测试、部署等全生命周期,帮助开发者通过联动云资源,迅速构建 Serverless 应用
  • Serverless Framework
  • Serverless Framework文档
  • 安装Serverless Framework
$ cnpm install -g serverless
$ cnpm update -g serverless
$ serverless -v

3. Serverless Components #

  • Serverless Components是支持多个云资源编排和组织的场景化解决方案,主要基于客户的具体场景,如 Express 框架支持、网站部署等
  • Serverless Components 可以有效简化云资源的配置和管理,将网关、COS 和 CAM 等产品联动起来,让客户更多关注场景和业务
  • Serverless Framework Components 最佳实践
    • @serverless/tencent-scf - 腾讯云云函数组件
    • @serverless/tencent-express - 快速部署基于 Express.js 的后端服务到腾讯云函数的组件
    • @serverless/tencent-website - 快速部署静态网站到腾讯云的组件

3.1 云函数 SCF 组件 #

  • 腾讯云 SCF 云函数组件通过使用 Tencent Serverless Framework,基于云上 Serverless 服务(云函数及触发器等),实现0配置,便捷开发,极速部署您的第一个云函数
  • 查看scf
  • 全量配置

3.1.1 serverless.yml #

  • js-yaml

    tencent-scf\serverless.yml

# serverless.yml

component: scf # (必填) 引用 component 的名称,当前用到的是 tencent-scf 组件
name: scfdemo # (必填) 该组件创建的实例名称
org: test # (可选) 用于记录组织信息,默认值为您的腾讯云账户 appid
app: scfApp # (可选) 该 SCF 应用名称
stage: dev # (可选) 用于区分环境信息,默认值是 dev

inputs:
  name: scfFunctionName
  src: ./src
  runtime: Nodejs10.15 # 云函数的运行时环境。除 Nodejs10.15 外,可选值为:Python2.7、Python3.6、Nodejs6.10、Nodejs8.9、PHP5、PHP7、Golang1、Java8。
  region: ap-beijing
  handler: index.main_handler
  events:
    - apigw:
        name: serverless_api
        parameters:
          protocols:
            - http
            - https
          serviceName:
          description: The service of Serverless Framework
          environment: release
          endpoints:
            - path: /index
              method: GET

3.1.2 src\index.js #

tencent-scf\src\index.js

'use strict';
exports.main_handler = async (event, context, callback) => {
    console.log("Hello World")
    console.log(event)
    console.log(event["non-exist"])
    console.log(context)
    return "Hello World";
};

3.1.3 tencent-scf.env #

tencent-scf.env

  • 当前默认支持 CLI 扫描二维码登录,如您希望配置持久的环境变量/密钥信息,也可以本地创建 .env 文件:
  • API密钥管理

wechatlogin

TENCENT_APP_ID=
TENCENT_SECRET_ID=
TENCENT_SECRET_KEY=

3.1.4 布署 #

sls --debug

3.2 API 网关组件 #

  • API网关是将所有API的调用统一接入API网关层,由网关层负责接入和输出
  • API网关是用户与服务器的连接器,负责API接口的托管,实现安全防护和统一监控。
  • API网关组件是 serverless-tencent 组件库中的基础组件之一,您可以通过该组件快速且方便地创建、配置和管理腾讯云的 API 网关产品。
  • 通过 API 网关组件,您可以对一个 API 服务/接口进行完整的创建、配置、部署和删除等操作
  • 全量配置

3.2.1 tencent-api\serverless.yml #

# serverless.yml

restApi:
    component: "@serverless/tencent-apigateway"
    inputs:
      region: ap-beijing
      protocol: http
      serviceName: serverless
      environment: release
      endpoints:
        - path: /users
          method: GET
          function:
            functionName: scfFunctionName

3.2.2 布署 #

sls --debug
http://service-mpkd1e88-1258145019.gz.apigw.tencentcs.com/users

3.3 布署静态网站 #

  • 完整配置

3.3.1 serverless.yml #

staticwebsite\serverless.yml

component: website # (必填) 引用 component 的名称,当前用到的是 tencent-website 组件
name: websitedemo # (必填) 该 website 组件创建的实例名称
org: test # (可选) 用于记录组织信息,默认值为您的腾讯云账户 appid
app: websiteApp # (可选) 该 website 应用名称
stage: dev # (可选) 用于区分环境信息,默认值是 dev

inputs:
  code:
    src: ./code
    index: index.html
    error: index.html  
  region: ap-beijing
  bucketName: my-bucket

3.3.2 index.html #

staticwebsite\code\index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    static website
</body>

</html>

3.4 布署express项目 #

  • 全量配置

3.4.1 创建项目 #

mkdir tencent-express
cd tencent-express
npm init -y
cnpm i express -S

3.4.2 serverless.yml #

tencent-express\serverless.yml

org: orgDemo # (optional) serverless dashboard org. default is the first org you created during signup.
app: appDemo # (optional) serverless dashboard app. default is the same as the name property.
stage: dev # (optional) serverless dashboard stage. default is dev.
component: express # (required) name of the component. In that case, it's express.
name: expressDemo # (required) name of your express component instance.

inputs:
  src: ./
  region: ap-beijing
  runtime: Nodejs10.15
  apigatewayConf:
    protocols:
      - http
      - https
    environment: release

3.4.3 sls.js #

tencent-express\sls.js

const express = require('express')
const path = require('path')
const app = express()

app.get(`/*`, (req, res) => {
    res.send('i am express')
})
module.exports = app

3.5 布署express+layer项目 #

  • 层管理
  • 打包压缩阶段

3.5.1 serverless.yml #

tencent-express-layer\serverless.yml

org: orgDemo # (optional) serverless dashboard org. default is the first org you created during signup.
app: appDemo # (optional) serverless dashboard app. default is the same as the name property.
stage: dev # (optional) serverless dashboard stage. default is dev.
component: express # (required) name of the component. In that case, it's express.
name: expressLayerDemo # (required) name of your express component instance.

inputs:
  src:
    src: ./src # (optional) path to the source folder. default is a hello world app.
    exclude:
      - .env
  region: ap-beijing
  layers:
    - name: nodeLayer
      version: 1
  runtime: Nodejs10.15
  apigatewayConf:
    protocols:
      - http
      - https
    environment: release

3.5.2 src\sls.js #

tencent-express-layer\src\sls.js

const express = require('express')
const path = require('path')
const app = express()

app.get(`/*`, (req, res) => {
    res.sendFile(path.join(__dirname, 'index.html'))
})

app.use(function (err, req, res) {
    console.error(err)
    res.status(500).send('Internal Serverless Error')
})

module.exports = app

3.6 部署Vue+Express全栈应用 #

  • 全栈组件(Vue.js+Express.js)用于通过多个 Serverless Components 部署 Serverless 全栈应用程序
  • 可以帮助开发者更方便快捷的部署 Serverless 应用,例如利用后端 API 与前端 Vue.js 结合等场景
  • serverless Express.js 后端:由腾讯云 Serverless Cloud Function(云函数 SCF) 和腾讯云 API 网关提供相关能力,支持 express.js 框架,帮助开发者架构自己的项目和路由。
  • serverless Vue.js 前端:由腾讯云 Cloud Object Storage(对象存储 COS)提供相关存储能力,通过后端 API 传递到前端,并使用 Vue.js 做相关渲染

21ae7465b6927c14d9bc4ae6dc33fc17

3.6.1 serverless.yml #

vue-fullstack\serverless.yml

name: tencent-fullstack-vue-application

dashboard:
  component: '@serverless/tencent-website'
  inputs:
    code:
      src: dist
      root: dashboard
      hook: npm run build
    env:
      apiUrl: ${api.url}
api:
  component: '@serverless/tencent-express'
  inputs:
    code: ./api
    functionName: tencent-fullstack-vue-api
    apigatewayConf:
      protocols:
        - https

3.6.2 api\package.json #

vue-fullstack\api\package.json

{
  "name": "tencent-fullstack-vue-api",
  "version": "0.0.0",
  "dependencies": {
    "cors": "^2.8.5",
    "express": "^4.17.1"
  },
  "license": "ISC"
}

3.6.3 api\app.js #

vue-fullstack\api\app.js

'use strict'
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors());

app.get('/', (req, res) => {
    res.send(JSON.stringify({ message: `前端架构` }))
});

module.exports = app;

3.6.4 生成前端项目 #

vue create dashboard

3.6.5 src\App.vue #

vue-fullstack\dashboard\src\App.vue

<template>
  <div id="app">{{message}}</div>
</template>

<script>
import "../env";
export default {
  name: "App",
  data() {
    return {
      message: "message"
    };
  },
  mounted() {
    fetch(window.env.apiUrl)
      .then(res => res.json())
      .then(result => {
        this.message = result.message;
      });
  }
};
</script>

2.RBAC #

  • 基于角色的权限访问控制(Role-Based Access Control)
  • RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联
  • 一个用户拥有若干角色,每一个角色拥有若干权限。这样,就构造成用户-角色-权限的授权模型
  • 在这种模型中,用户与角色之间,角色与权限之间一般是多对多的关系
  • 在RBAC中最重要的概念包括:用户(User),角色(Role),权限(Permission)

2.1 示意图 #

rbacimage

rbac

2.2 表设计 #

2.2.1 用户表(user) #

字段 字段名 类型 默认
id ID int(11)
userName 用户名 varchar(255)
password 密码 varchar(255)
CREATE TABLE `user`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `userName` varchar(255),
  `password` varchar(255),
  PRIMARY KEY (`id`) 
)

INSERT INTO `user` VALUES (1, 'isadmin', '123456');
INSERT INTO `user` VALUES (2, 'isuser', '123456');

2.2.2 角色表(role) #

字段 字段名 类型 默认
id ID int(11)
name 名称 varchar(255)
desc 描述 varchar(255)
CREATE TABLE `role`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) ,
  `desc` varchar(255) ,
  PRIMARY KEY (`id`) 
) E

INSERT INTO `role` VALUES (1, 'admin', '管理员');
INSERT INTO `role` VALUES (2, 'user', '普通用户');

2.2.3 权限表(permission) #

字段 字段名 类型 默认
id ID int(11)
name 名称 varchar(255)
parent_id 父ID int(11)
icon 图标 varchar(255)
key 路径 varchar(255)
type 类型 varchar(32)
CREATE TABLE `permission`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) ,
  `parent_id` int(11) NULL DEFAULT NULL,
  `icon` varchar(255) ,
  `key` varchar(255) ,
  `type` varchar(255) ,
  PRIMARY KEY (`id`) 
);

INSERT INTO `permission` VALUES (1, '授权平台', 0, 'desktop', '/api', 'menu');
INSERT INTO `permission` VALUES (2, '角色管理', 1, 'team', '/api/role', 'menu');
INSERT INTO `permission` VALUES (3, '用户管理', 1, 'user', '/api/user', 'menu');
INSERT INTO `permission` VALUES (4, '权限管理', 1, 'idcard', '/api/resource', 'menu');
INSERT INTO `permission` VALUES (5, '添加用户', 3, 'team', '/api/user/add', 'button');
INSERT INTO `permission` VALUES (6, '删除用户', 3, 'team', '/api/user/delete', 'button');

2.2.4 角色用户表(role_user) #

字段 字段名 类型
role_id 角色ID int(11)
user_id 用户ID int(11)
DROP TABLE IF EXISTS `role_user`;
CREATE TABLE `role_user`  (
  `role_id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  PRIMARY KEY (`user_id`, `role_id`) 
) 

INSERT INTO `role_user` VALUES (1, 1);
INSERT INTO `role_user` VALUES (2, 2);

2.2.5 角色权限(role_permission) #

字段 字段名 类型
role_id 角色ID int(11)
permission_id 资源ID int(11)
CREATE TABLE `role_permission`  (
  `role_id` int(11) NOT NULL,
  `permission_id` int(255) NOT NULL,
  PRIMARY KEY (`role_id`, `permission_id`) 
) 

INSERT INTO `role_permission` VALUES (1, 1);
INSERT INTO `role_permission` VALUES (1, 2);
INSERT INTO `role_permission` VALUES (1, 3);
INSERT INTO `role_permission` VALUES (1, 4);
INSERT INTO `role_permission` VALUES (1, 5);
INSERT INTO `role_permission` VALUES (1, 6);
INSERT INTO `role_permission` VALUES (2, 1);
INSERT INTO `role_permission` VALUES (2, 4);

2.2.6 数据库脚本 #

  • cms.sql

3.egg.js #

  • tencent-egg

3.1. 初始化项目 #

$ mkdir egg-cms && cd egg-cms
$ cnpm init egg --type=simple
$ cnpm i

3.2. 添加模块 #

  • mysql
  • redis
$ cd egg-cms
$ npm install egg-sequelize mysql2 egg-jwt egg-redis --save

3.3. config\plugin.js #

'use strict';

module.exports = {
  sequelize: {
    enable: true,
    package: "egg-sequelize"
  },
  jwt: {
    enable: true,
    package: "egg-jwt"
  },
  redis: {
    enable: true,
    package: "egg-redis"
  }
};

3.4. config\config.default.js #

/* eslint valid-jsdoc: "off" */

'use strict';

/**
 * @param {Egg.EggAppInfo} appInfo app info
 */
module.exports = appInfo => {
  /**
   * built-in config
   * @type {Egg.EggAppConfig}
   **/
  const config = exports = {};

  // use for cookie sign key, should change to your own and keep security
  config.keys = appInfo.name + '_1588409777990_9883';

  // add your middleware config here
  config.middleware = [];

  // add your user config here
  const userConfig = {
+    security: {
+      csrf: false
+    },
+    sequelize: {
+      dialect: "mysql",
+      host: "localhost",
+      port: "3306",
+      database: "egg-cms",
+      username: "root",
+      password: "5f8b8a5d650637f8"
+    },
+    redis: {
+      client: {
+        port: 6379,          // Redis port
+        host: '127.0.0.1',   // Redis host
+        password: 'auth',
+        db: 0,
+      },
+    }
  };

  return {
    ...config,
    ...userConfig,
  };
};

3.5. model\user.js #

app\model\user.js

module.exports = app => {
    const { STRING, INTEGER, DATE } = app.Sequelize;
    const User = app.model.define("user", {
        id: { type: INTEGER, primaryKey: true, autoIncrement: true },
        userName: STRING(30),
        password: STRING(30),
        created_at: DATE,
        updated_at: DATE
    });
    return User;
};

3.6. app\controller\home.js #

  • jwt.io

app\controller\home.js

'use strict';

const Controller = require('egg').Controller;

class HomeController extends Controller {
  async index() {
    const { ctx } = this;
    ctx.body = 'hi, egg';
  }
  async currentUser() {
    const { ctx } = this;
    const { user } = ctx.state;
    this.ctx.body = {
      name: user.userName,
      avatar: 'http://img.zhufengpeixun.cn/tuizi.jpg',
      userid: user.id
    }
  }
  async login() {
    const { ctx, app } = this;
    let { userName, password } = ctx.request.body;
    const users = await ctx.model.User.findAll({
      where: { userName, password },
      limit: 1
    });
    if (users.length > 0) {
      let user = users[0];
      ctx.status = 200;
      const token = app.jwt.sign(
        {
          id: user.id,
          userName: user.userName
        },
        app.config.jwt.secret,
        {
          expiresIn: "1h"
        }
      );
      await app.redis.set(`token_${user.id}`, token);
      ctx.body = {
        status: 'ok',
        type: 'account',
        currentAuthority: 'admin',
        token
      }
    } else {
      ctx.body = {
        status: 'error'
      }
    }
  }
}

module.exports = HomeController;

3.7. app\router.js #

app\router.js

module.exports = app => {
  const { router, controller, jwt } = app;
  router.get('/', controller.home.index);
+  router.post('/api/login/account', controller.home.login);
+  router.get('/api/currentUser', jwt, controller.home.currentUser);
};

3.8. app.js #

app.js

class AppBootHook {
    constructor(app) {
        this.app = app;
    }

    async willReady() {
        await this.app.model.sync({ logging: console.log, force: true });
        await this.app.model.query(
            "INSERT INTO users (user_name, password) VALUES ('admin', '123456')"
        );
    }
}

module.exports = AppBootHook;

4. 前端项目 #

4.1. 启动项目 #

  • pro.ant.design
  • create-umi
umi -v
cnpm create umi

4.2 config\config.ts #

config\config.ts

export default {
  dev: {
+    '/server/api/': {
+      target: 'http://127.0.0.1:7001',
+      changeOrigin: true,
+      pathRewrite: { '^/server': '' },
+    },
    /* '/api/': {
      target: 'https://preview.pro.ant.design',
      changeOrigin: true,
      pathRewrite: { '^': '' },
    }, */
  },
  test: {
    '/api/': {
      target: 'https://preview.pro.ant.design',
      changeOrigin: true,
      pathRewrite: { '^': '' },
    },
  },
  pre: {
    '/api/': {
      target: 'your pre url',
      changeOrigin: true,
      pathRewrite: { '^': '' },
    },
  },
};

4.3 services\login.ts #

src\services\login.ts

export async function fakeAccountLogin(params: LoginParamsType) {
+  return request('/server/api/login/account', {
    method: 'POST',
    data: params,
  });
}

4.4 services\user.ts #

src\services\user.ts

export async function queryCurrent(): Promise<any> {
+  return request('/server/api/currentUser');
}

4.5 models\login.ts #

src\models\login.ts

effects: {
    *login({ payload }, { call, put }) {
      const response = yield call(fakeAccountLogin, payload);
      yield put({
        type: 'changeLoginStatus',
        payload: response,
      });
      // Login successfully
      if (response.status === 'ok') {
+        if (response.token) {
+          localStorage.setItem('token', response.token);
+        }
        const urlParams = new URL(window.location.href);

4.6 utils\request.ts #

src\utils\request.ts

const request = extend({
  errorHandler, // 默认错误处理
  credentials: 'include', // 默认请求是否带上cookie
});
+request.interceptors.request.use((url: any, options: any) => {
+  if (localStorage.getItem('token')) {
+    options.headers.Authorization = 'Bearer ' + localStorage.getItem('token')
+  }
+  return { url, options };
+});
export default request;

访问验证

请输入访问令牌

Token不正确,请重新输入