一步步实现微服务权限管理系统(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
接下来
路由数据也需要进行持久化