Skip to content

一步步实现微服务权限管理系统(7)

前言

  • 前端参考了很多框架,可谓百花齐放,但很多封装过剩,不利于学习和应用,最终我选择了 [vue-pure-admin](https://github.com/pure-admin/vue-pure-admin)
  • 后端我将使用 go-zero 来带领大家一步步实现一个权限管理系统
  • 本系列项目存放在 purezeroadmin 中,每一部分我都将打tag,并保证每个tag能正常运行。请多点赞和评论。
  • 后面示例均为 purezeroadmin 项目为例,你们可以根据需要自建工程来进行试验。均采用vscode进行试验。
  • go-zero 常用命令我将放入其对应的 makefile 文件中。

本节概述

  • 之前数据都是模拟的,现在需要将数据持久化,这里我选择使用mysql。
  • 本节及之后的后端辅助函数示例请自行查看utls目录下的文件

后端修改

增加docker-compose.yaml 文件,创建测试mysql数据库

services:
  mysql:
    restart: always
    privileged: true
    image: mysql:8.0.40
    container_name: purezeroadmin
    volumes:
      - ./data/mysql:/var/lib/mysql
    command:
      --default-authentication-plugin=mysql_native_password
      --explicit_defaults_for_timestamp=true
      --max_connections=5000
    environment:  
      TZ: Asia/Shanghai
      MYSQL_ROOT_PASSWORD: "123456"
      MYSQL_INITDB_SKIP_TZINFO: "Asia/Shanghai"
      LANG: C.UTF-8 
    ports:
      - 55506:3306

启动mysql后创建测试数据库和表

/*!40101 SET NAMES utf8mb4 */;

/*!40101 SET SQL_MODE=''*/;

/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`purezeroadmin` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */;

USE `purezeroadmin`;

/*Table structure for table `tb_role` */

CREATE TABLE `tb_role` (
  `name` varchar(32) NOT NULL,
  `permissions` json NOT NULL,
  `create_ts` bigint NOT NULL,
  `update_ts` bigint NOT NULL,
  PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

/*Data for the table `tb_role` */

insert  into `tb_role`(`name`,`permissions`,`create_ts`,`update_ts`) values ('admin','[\"*:*:*\"]',1,1);
insert  into `tb_role`(`name`,`permissions`,`create_ts`,`update_ts`) values ('common','[\"permission:btn:add\", \"permission:btn:edit\"]',2,2);

/*Table structure for table `tb_user` */

CREATE TABLE `tb_user` (
  `user_id` bigint NOT NULL AUTO_INCREMENT,
  `username` varchar(64) NOT NULL,
  `password` varchar(256) NOT NULL,
  `nickname` varchar(64) NOT NULL,
  `avatar` varchar(256) NOT NULL,
  `roles` json NOT NULL,
  `create_ts` bigint NOT NULL,
  `update_ts` bigint NOT NULL,
  PRIMARY KEY (`user_id`),
  UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

/*Data for the table `tb_user` */

insert  into `tb_user`(`user_id`,`username`,`password`,`nickname`,`avatar`,`roles`,`create_ts`,`update_ts`) values (1,'admin','0192023a7bbd73250516f069df18b500','小铭','https://avatars.githubusercontent.com/u/44761321','[\"admin\"]',20060102150405,20060102150405);
insert  into `tb_user`(`user_id`,`username`,`password`,`nickname`,`avatar`,`roles`,`create_ts`,`update_ts`) values (2,'common','f9851fac6a5fa7f2500099c8715cc436','小林','https://avatars.githubusercontent.com/u/52823142','[\"admin\", \"common\"]',20060102150405,20060102150405);

生成 models

goctl model mysql datasource --url "root:123456@tcp(127.0.0.1:55506)/purezeroadmin"  -t="*" --dir user-api/models --home template

配置增加mysql连接信息

# mysql dsn
Dsn: "root:123456@tcp(127.0.0.1:55506)/purezeroadmin?charset=utf8mb4&parseTime=true&loc=Local"

user-api/internal/config/config.go同理

type Config struct {
    rest.RestConf
    Auth struct { // JWT 认证需要的密钥和过期时间配置
        AccessSecret string
        AccessExpire int64 // 单位为秒
    }
    Dsn string // mysql dsn
}

user-api/internal/svc/servicecontext.go 增加mysql相关model初始化

package svc

import (
    "backend/user-api/internal/config"
    "backend/user-api/models"

    "github.com/zeromicro/go-zero/core/stores/sqlx"
)

type ServiceContext struct {
    Config      config.Config
    TbUserModel models.TbUserModel
    TbRoleModel models.TbRoleModel
}

func NewServiceContext(c config.Config) *ServiceContext {
    conn := sqlx.NewMysql(c.Dsn)
    return &ServiceContext{
        Config:      c,
        TbUserModel: models.NewTbUserModel(conn),
        TbRoleModel: models.NewTbRoleModel(conn),
    }
}

user-api/internal/logic/userloginlogic.go 登陆逻辑修改

func (l *UserLoginLogic) UserLogin(req *types.UserLoginReq) (resp *types.UserLoginResp, err error) {

    tbUser, err := l.svcCtx.TbUserModel.FindOneByUsername(l.ctx, req.UserName)
    if err != nil {
        return nil, err
    }

    if tbUser.Password != codeutil.Md5Str(req.Password) {
        return nil, errors.New("用户或密码错误")
    }

    roles, err := jsonutil.ToArray[string](tbUser.Roles)
    if err != nil {
        return nil, err
    }

    var permissions []string
    for _, role := range roles {
        tbRole, err := l.svcCtx.TbRoleModel.FindOne(l.ctx, role)
        if err != nil {
            return nil, err
        }

        rolePermissions, err := jsonutil.ToArray[string](tbRole.Permissions)
        if err != nil {
            return nil, err
        }

        permissions = arrutil.UniqueConcat(permissions, rolePermissions)
    }

    tNow := time.Now()
    tExpire := tNow.Add(time.Second * time.Duration(l.svcCtx.Config.Auth.AccessExpire))

    mPayload := map[string]any{
        global.CtxJwtUserIDKey: tbUser.UserId,
    }

    accessToken, err := jwtutil.GetToken(l.svcCtx.Config.Auth.AccessSecret, tNow.Unix(), tExpire.Unix(), mPayload)
    if err != nil {
        return nil, err
    }

    refreshToken, err := jwtutil.GetToken(l.svcCtx.Config.Auth.AccessSecret, tNow.Unix(), tExpire.Unix()+86400, mPayload)
    if err != nil {
        return nil, err
    }

    return &types.UserLoginResp{
        Avatar:       tbUser.Avatar,
        Username:     tbUser.Username,
        Nickname:     tbUser.Nickname,
        Roles:        roles,
        Permissions:  permissions,
        AccessToken:  accessToken,
        RefreshToken: refreshToken,
        Expires:      tExpire.Format("2006/01/02 15:04:05"),
    }, nil
}

测试

  • 前后端分别启动测试,正常

tag版本

purezeroadmin 项目下

git checkout v1.6.0

接下来

路由数据也需要进行持久化

Comments