[golang gin framework] 46. Gin mall project - after the microservice actual combat, the background Rbac client calls the microservice permission verification and the Rbac microservice database extraction

1.  Dynamically display the left menu microservice according to the user's permissions

1. Introduce

The background Rbac client calls the microservice permission verification function mainlydisplay the user name after login, dynamically display the left menu according to the user's permission, judge the permission of the currently logged in user, and deny access if there is no permission, refer to [ golang gin framework] 14. Gin mall project-RBAC management , the function of this microservice is the same as the previous section [golang gin framework] 45.Gin mall project-after the actual combat of microservice, the role permission association function of background Rbac microservice is the same , because controllers/admin/mainController. The Index() method of go is to obtain a list of all permissions, as well as the permissions owned by the current role, the code is as follows:


func (con MainController) Index(c *gin.Context) {
	//获取Session里面保存的用户信息
	session := sessions.Default(c)
	userinfo := session.Get("userinfo_admin")
	//判断Session中的用户信息是否存在,如果不存在跳转到登录页面(注意需要判断) 如果存在继续向下执行
	//session.Get获取返回的结果是一个空接口类型,所以需要进行类型断言: 判断userinfo是不是一个string
	userinfoStr, ok := userinfo.(string)
	if ok { // 说明是一个string
		//1.获取用户信息
		var userinfoStruct []models.Manager
		//把获取到的用户信息转换结构体
		json.Unmarshal([]byte(userinfoStr), &userinfoStruct)

		//获取所有权限列表
		accessList := []models.Access{}
		models.DB.Where("module_id = ?", 0).Preload("AccessItem", func(db *gorm.DB) *gorm.DB {
			return db.Order("access.sort DESC")
		}).Order("sort DESC").Find(&accessList)

		//获取当前角色拥有的权限,并把权限id放在一个map对象中
		roleAccess := []models.RoleAccess{}
		models.DB.Where("role_id = ?", userinfoStruct[0].RoleId).Find(&roleAccess)
		roleAccessMap := make(map[int]int)
		for _, v := range roleAccess {
			roleAccessMap[v.AccessId] = v.AccessId
		}

		//循环遍历所有权限数据,判断当前权限的id是否在角色权限的map对象中,如果是的话给当前数据加入checked属性
		for i := 0; i < len(accessList); i++ { //循环权限列表
			if _, ok := roleAccessMap[accessList[i].Id]; ok { // 判断当前权限是否在角色权限的map对象中
				accessList[i].Checked = true
			}
			for j := 0; j < len(accessList[i].AccessItem); j++ { // 判断当前权限的子栏位是否在角色权限的map中
				if _, ok := roleAccessMap[accessList[i].AccessItem[j].Id]; ok { // 判断当前权限是否在角色权限的map对象中
					accessList[i].AccessItem[j].Checked = true
				}
			}
		}

		c.HTML(http.StatusOK, "admin/main/index.html", gin.H{
			"username": userinfoStruct[0].Username,
			"isSuper": userinfoStruct[0].IsSuper,  // 是否超级管理员, 超级管理员显示全部
			"accessList": accessList,
		})
	} else {
		c.Redirect(http.StatusFound, "/admin/login")
	}
}

2. Improve the RoleAuth() method under handler/rbacRole.go

The above code is similar to the RoleAuth() method under handler/rbacRole.go in the previous section . The difference is that it has a sorting function . Replace the above sorted code with the corresponding code in the microservice RoleAuth() , and then in controllers/admin/ Just call the RoleAuth() method of this microservice in the Index() method of mainController.go. After replacement, the code of the RoleAuth() method under handler/rbacRole.go is as follows:

//授权
func (e *RbacRole) RoleAuth(ctx context.Context, req *pb.RoleAuthRequest, res *pb.RoleAuthResponse) error {
	//1、获取角色id  req.RoleId
	//获取所有权限列表
	accessList := []models.Access{}

	models.DB.Where("module_id = ?", 0).Preload("AccessItem", func(db *gorm.DB) *gorm.DB {
		return db.Order("access.sort DESC")
	}).Order("sort DESC").Find(&accessList)

	//获取当前角色拥有的权限,并把权限id放在一个map对象中
	roleAccess := []models.RoleAccess{}
	models.DB.Where("role_id = ?",  req.RoleId).Find(&roleAccess)
	roleAccessMap := make(map[int]int)
	for _, v := range roleAccess {
		roleAccessMap[v.AccessId] = v.AccessId
	}

	//循环遍历所有权限数据,判断当前权限的id是否在角色权限的map对象中,如果是的话给当前数据加入checked属性
	for i := 0; i < len(accessList); i++ { //循环权限列表
		if _, ok := roleAccessMap[int(accessList[i].Id)]; ok { // 判断当前权限是否在角色权限的map对象中, 需要进行类型转换
			accessList[i].Checked = true
		}
		for j := 0; j < len(accessList[i].AccessItem); j++ { // 判断当前权限的子栏位是否在角色权限的map中
			if _, ok := roleAccessMap[int(accessList[i].AccessItem[j].Id)]; ok { // 判断当前权限是否在角色权限的map对象中
				accessList[i].AccessItem[j].Checked = true
			}
		}
	}
	//处理数据:进行类型转换匹配操作
	var tempList []*pb.AccessModel
	for _, v := range accessList {
		var tempItemList []*pb.AccessModel
		for _, k := range v.AccessItem {
			tempItemList = append(tempItemList, &pb.AccessModel{
				Id:          int64(k.Id),
				ModuleName:  k.ModuleName,
				ActionName:  k.ActionName,
				Type:        int64(k.Type),
				Url:         k.Url,
				ModuleId:    int64(k.ModuleId),
				Sort:        int64(k.Sort),
				Description: k.Description,
				Status:      int64(k.Status),
				Checked:     k.Checked, //注意,不要忘了角色是否有这个权限的判断
				AddTime:     int64(k.AddTime),
			})
		}
		tempList = append(tempList, &pb.AccessModel{
			Id:          int64(v.Id),
			ModuleName:  v.ModuleName,
			ActionName:  v.ActionName,
			Type:        int64(v.Type),
			Url:         v.Url,
			ModuleId:    int64(v.ModuleId),
			Sort:        int64(v.Sort),
			Description: v.Description,
			Status:      int64(v.Status),
			AddTime:     int64(v.AddTime),
			Checked:     v.Checked,  //注意,不要忘了角色是否有这个权限的判断
			AccessItem:  tempItemList,
		})
	}

	res.AccessList = tempList

	return nil
}

3. Index() of controllers/admin/mainController.go calls the RoleAuth() method of the microservice to determine whether to display the corresponding menu

Then call the RoleAuth() method of this microservice in the Index() method of controllers/admin/mainController.go, the code is as follows:


func (con MainController) Index(c *gin.Context) {
	//获取Session里面保存的用户信息
	session := sessions.Default(c)
	userinfo := session.Get("userinfo_admin")
	//判断Session中的用户信息是否存在,如果不存在跳转到登录页面(注意需要判断) 如果存在继续向下执行
	//session.Get获取返回的结果是一个空接口类型,所以需要进行类型断言: 判断userinfo是不是一个string
	userinfoStr, ok := userinfo.(string)
	if ok { // 说明是一个string
		//1.获取用户信息
		var userinfoStruct []models.Manager
		//把获取到的用户信息转换结构体
		json.Unmarshal([]byte(userinfoStr), &userinfoStruct)

		//调用微服务获取当前角色拥有权限(菜单)
		rbacClient := pbRbac.NewRbacRoleService("rbac", models.RbacClient)
		res, _ := rbacClient.RoleAuth(context.Background(), &pbRbac.RoleAuthRequest{
			RoleId: int64(userinfoStruct[0].RoleId),
		})

		c.HTML(http.StatusOK, "admin/main/index.html", gin.H{
			"username":   userinfoStruct[0].Username,
			"accessList": res.AccessList,  // 从微服务返回中获取数据
			"isSuper":    userinfoStruct[0].IsSuper, // 是否超级管理员, 超级管理员显示全部
		})
	} else {
		c.Redirect(http.StatusFound, "/admin/login")
	}
}

After verification, it is found that there is no problem, so I will not explain it here, because the microservice RoleAuth() method has basically not changed, but the Index method of mainControllers.go in the background is called.

2. Judgment of authority: users who have not logged in cannot enter the background management center

1. Extract the adminAuth.go middleware code and make it a microservice method

(1).Proto/rbacRole.proto adds rpc MiddlewaresAuth method

Judgment of permissions  here : Users who have not logged in cannot enter the background management center. The function used to be judged in the middlewares/adminAuth.go middleware . Now, the logic code inside is extracted and made into a microservice. First come Take a look at the code inside the adminAuth.go middleware :

package middlewares

//中间件: 作用: 在执行路由之前或者之后进行相关逻辑判断

import (
	"encoding/json"
	"fmt"
	"github.com/gin-contrib/sessions"
	"github.com/gin-gonic/gin"
	"gopkg.in/ini.v1"
	"goshop/models"
	"net/http"
	"os"
	"strings"
)

func InitAdminAuthMiddleware(c *gin.Context) {
	//权限判断: 没有登录的用户不能进入后台管理中心

	//1、获取Url访问的地址
	//当地址后面带参数时:,如: admin/captcha?t=0.8706946438889653,需要处理
	//strings.Split(c.Request.URL.String(), "?"): 把c.Request.URL.String()请求地址按照?分割成切片
	pathname := strings.Split(c.Request.URL.String(), "?")[0]

	//2、获取Session里面保存的用户信息
	session := sessions.Default(c)
	userinfo := session.Get("userinfo_admin")
	//3、判断Session中的用户信息是否存在,如果不存在跳转到登录页面(注意需要判断) 如果存在继续向下执行
	//session.Get获取返回的结果是一个空接口类型,所以需要进行类型断言: 判断userinfo是不是一个string
	userinfoStr, ok := userinfo.(string)
	if ok { // 说明是一个string
		var userinfoStruct []models.Manager
		//把获取到的用户信息转换结构体
		err := json.Unmarshal([]byte(userinfoStr), &userinfoStruct)
		if err != nil || !(len(userinfoStruct) > 0 && userinfoStruct[0].Username != "") {
			if pathname != "/admin/login" && pathname != "/admin/dologin" && pathname != "/admin/captcha" {
				//跳转到登录页面
				c.Redirect(http.StatusFound, "/admin/login")
			}
		} else { //表示用户登录成功
			//获取当前访问的URL对应的权限id,判断权限id是否在角色对应的权限中
			// strings.Replace 字符串替换
			urlPath := strings.Replace(pathname, "/admin/", "", 1)
			//排除权限判断:不是超级管理员并且不在相关权限内
			if userinfoStruct[0].IsSuper == 0 && !excludeAuthPath("/" + urlPath){
				//判断用户权限:当前用户权限是否可以访问url地址
				//获取当前角色拥有的权限,并把权限id放在一个map对象中
				roleAccess := []models.RoleAccess{}
				models.DB.Where("role_id = ?", userinfoStruct[0].RoleId).Find(&roleAccess)
				roleAccessMap := make(map[int]int)
				for _, v := range roleAccess {
					roleAccessMap[v.AccessId] = v.AccessId
				}
				//实例化access
				access := models.Access{}
				//查询权限id
				models.DB.Where("url = ? ", urlPath).Find(&access)
				//判断权限id是否在角色对应的权限中
				if _, ok := roleAccessMap[access.Id]; !ok {
					c.String(http.StatusOK, "没有权限")
					c.Abort() // 终止程序
				}
			}
		}
	} else {
		//4、如果Session不存在,判断当前访问的URl是否是login doLogin captcha,如果不是跳转到登录页面,如果是不行任何操作
		//说明用户没有登录
		//需要排除到不需要做权限判断的路由
		if pathname != "/admin/login" && pathname != "/admin/dologin" && pathname != "/admin/captcha" {
			//跳转到登录页面
			c.Redirect(http.StatusFound, "/admin/login")
		}
	}
}

//排除权限判断的方法
func excludeAuthPath(urlPath string) bool {
	//加载配置文件
	cfg, err := ini.Load("./conf/app.ini")
	if err != nil {
		fmt.Printf("Fail to read file: %v", err)
		os.Exit(1)
	}
	//获取需要排除的地址
	excludeAuthPath := cfg.Section("").Key("excludeAuthPath").String()
	//拆分字符串成为一个切片
	excludeAuthPathSlice := strings.Split(excludeAuthPath, ",")
	//判断传入的地址是否在排除地址内
	for _, v := range excludeAuthPathSlice {
		if v == urlPath {
			return true
		}
	}
	return false
}

From the above code, it can be seen that after the user logs in successfully, it is necessary to determine whether the permission id corresponding to the url to be accessed is in the permission of the corresponding role , so when building a microservice method, it is necessary to pass in the urlPath to be accessed , and Role id, here put the microservice method into the rbacRole microservice, so add the rpc method under service RbacRole under proto/rbacRole.proto on the server side, as follows:

//权限判断:获取当前访问的URL对应的权限id,判断权限id是否在角色对应的权限中
rpc  MiddlewaresAuth(MiddlewaresAuthRequest) returns (MiddlewaresAuthResponse) {}

Then implement the above rpc method:

//权限判断:角色是否有访问urlPath的权限,请求参数
message MiddlewaresAuthRequest{
	int64 roleId=1;
	string urlPath=2;
}
//权限判断:响应参数 是否具有该访问权限
message MiddlewaresAuthResponse{
	bool hasPermission=1;
}

The complete code is as follows: 

syntax = "proto3";

package rbac;

option go_package = "./proto/rbacRole";

//角色管理
service RbacRole {
    //获取角色rpc方法: 请求参数RoleGetRequest, 响应参数RoleGetResponse
	rpc RoleGet(RoleGetRequest) returns (RoleGetResponse) {}
	//增加角色rpc方法: 请求参数RoleAddRequest, 响应参数RoleAddResponse
	rpc RoleAdd(RoleAddRequest) returns (RoleAddResponse) {}
	//编辑角色rpc方法: 请求参数RoleEditRequest, 响应参数RoleEditResponse
	rpc RoleEdit(RoleEditRequest) returns (RoleEditResponse) {}
	//删除角色rpc方法: 请求参数RoleDeleteRequest, 响应参数RoleDeleteResponse
	rpc RoleDelete(RoleDeleteRequest) returns (RoleDeleteResponse) {}

    //授权
	rpc RoleAuth(RoleAuthRequest) returns (RoleAuthResponse) {}
	//授权提交
    rpc RoleDoAuth(RoleDoAuthRequest) returns (RoleDoAuthResponse) {}

    //权限判断:获取当前访问的URL对应的权限id,判断权限id是否在角色对应的权限中
    rpc  MiddlewaresAuth(MiddlewaresAuthRequest) returns (MiddlewaresAuthResponse) {}
}

//角色相关model
message RoleModel{
	int64 id=1;
	string title=2;
	string description=3;
	int64 status=4;
	int64 addTime =5;
}

//权限相关模型:参考models/access.go
message AccessModel{
	int64 id=1;
	string moduleName =2;
	string actionName=3;
	int64 type=4;
	string url=5;
	int64 moduleId=6;
	int64 sort =7;
	string description=8;
	int64 status=9;
 	int64 addTime=10;
	bool checked=11;
	repeated AccessModel accessItem=12;
}

//获取角色请求参数
message RoleGetRequest{
    //角色id
	int64 id =1;
}

//获取角色响应参数
message RoleGetResponse{
    //角色model切片
	repeated RoleModel roleList=1;
}

//增加角色请求参数
message RoleAddRequest{
    //角色名称
	string title=1;
	//说明
	string description=2;
	//状态
	int64 status=3;
	//增加时间
	int64 addTime =4;
}

//增加角色响应参数
message RoleAddResponse{
    //是否增加成功
	bool success=1;
	//返回状态说明
	string message=2;
}

//编辑角色请求参数
message RoleEditRequest{
    //角色id
	int64 id=1;
	//角色名称
	string title=2;
	//说明
	string description=3;
	//状态
	int64 status=4;
	//增加时间
	int64 addTime =5;
}

//编辑角色响应参数
message RoleEditResponse{	
	//是否编辑成功
    bool success=1;
    //返回状态说明
    string message=2;
}

//删除角色请求参数
message RoleDeleteRequest{
	//角色id
	int64 id=1;
}

//删除角色响应参数
message RoleDeleteResponse{	
	//是否删除成功
    bool success=1;
    //返回状态说明
    string message=2;
}

//角色授权参数
message RoleAuthRequest{
	int64 roleId=1;
}
//角色授权响应参数
message RoleAuthResponse{
	repeated AccessModel accessList=1;
}

//角色授权提交参数
message RoleDoAuthRequest{
	int64 roleId=1;
	repeated string accessIds=2;
}

//角色授权提交响应参数
message RoleDoAuthResponse{
	bool success=1;
	string message=2;
}

//权限判断:角色是否有访问urlPath的权限,请求参数
message MiddlewaresAuthRequest{
	int64 roleId=1;
	string urlPath=2;
}
//权限判断:响应参数 是否具有该访问权限
message MiddlewaresAuthResponse{
	bool hasPermission=1;
}

 (2). The method of updating the corresponding rbacRole under the proto folder

Run the command protoc --proto_path=. --micro_out=. --go_out=:.proto/rbacRole.proto to update the files under proto

 (3). Implement the above rpc MiddlewaresAuth method under .handler/rbacRole.go

Extract the code related to judging user permissions from the middleware middlewares/adminAuth.go to make a MiddlewaresAuth() microservice method , the code is as follows:


//权限判断
func (e *RbacRole) MiddlewaresAuth(ctx context.Context, req *pb.MiddlewaresAuthRequest, res *pb.MiddlewaresAuthResponse) error {
	//判断用户权限:当前用户权限是否可以访问url地址
	// 1、根据角色获取当前角色的权限列表,然后把权限id放在一个map类型的对象里面
	roleAccess := []models.RoleAccess{}
	models.DB.Where("role_id=?", req.RoleId).Find(&roleAccess)
	roleAccessMap := make(map[int]int)
	for _, v := range roleAccess {
		roleAccessMap[v.AccessId] = v.AccessId
	}
	// 2、获取当前访问的url对应的权限id 判断权限id是否在角色对应的权限
	// pathname      /admin/manager
	access := models.Access{}
	models.DB.Where("url = ?", req.UrlPath).Find(&access)
	//3、判断当前访问的url对应的权限id 是否在权限列表的id中
	if _, ok := roleAccessMap[int(access.Id)]; !ok {
		res.HasPermission = false
	} else {
		res.HasPermission = true
	}
	return nil
}

2. The project-side middleware adminAuth.go calls the above microservice method to judge permissions

(1). Copy the rbacRole.go and rbacRole folders under the proto on the server side to the proto of the project

Because the rbacRole.proto in the server has been modified, it needs to be synchronized

(2). Call the authority judgment microservice method in the middlewares/adminAuth.go middleware of the project

package middlewares

//中间件: 作用: 在执行路由之前或者之后进行相关逻辑判断

import (
	"encoding/json"
	"fmt"
	"github.com/gin-contrib/sessions"
	"github.com/gin-gonic/gin"
	"gopkg.in/ini.v1"
	"goshop/models"
	pbRbac "goshop/proto/rbacRole"
	"net/http"
	"os"
	"context"
	"strings"
)

func InitAdminAuthMiddleware(c *gin.Context) {
	//权限判断: 没有登录的用户不能进入后台管理中心

	//1、获取Url访问的地址
	//当地址后面带参数时:,如: admin/captcha?t=0.8706946438889653,需要处理
	//strings.Split(c.Request.URL.String(), "?"): 把c.Request.URL.String()请求地址按照?分割成切片
	pathname := strings.Split(c.Request.URL.String(), "?")[0]

	//2、获取Session里面保存的用户信息
	session := sessions.Default(c)
	userinfo := session.Get("userinfo_admin")
	//3、判断Session中的用户信息是否存在,如果不存在跳转到登录页面(注意需要判断) 如果存在继续向下执行
	//session.Get获取返回的结果是一个空接口类型,所以需要进行类型断言: 判断userinfo是不是一个string
	userinfoStr, ok := userinfo.(string)
	if ok { // 说明是一个string
		var userinfoStruct []models.Manager
		//把获取到的用户信息转换结构体
		err := json.Unmarshal([]byte(userinfoStr), &userinfoStruct)
		if err != nil || !(len(userinfoStruct) > 0 && userinfoStruct[0].Username != "") {
			if pathname != "/admin/login" && pathname != "/admin/dologin" && pathname != "/admin/captcha" {
				//跳转到登录页面
				c.Redirect(http.StatusFound, "/admin/login")
			}
		} else { //表示用户登录成功
			//获取当前访问的URL对应的权限id,判断权限id是否在角色对应的权限中
			// strings.Replace 字符串替换
			urlPath := strings.Replace(pathname, "/admin/", "", 1)
			//排除权限判断:不	是超级管理员并且不在相关权限内
			if userinfoStruct[0].IsSuper == 0 && !excludeAuthPath("/" + urlPath){
				//判断用户权限:当前用户权限是否可以访问url地址
				//调用微服务进行权限判断
				rbacClient := pbRbac.NewRbacRoleService("rbac", models.RbacClient)
				res, _ := rbacClient.MiddlewaresAuth(context.Background(), &pbRbac.MiddlewaresAuthRequest{
					RoleId:  int64(userinfoStruct[0].RoleId),
					UrlPath: urlPath,
				})
				//3、判断当前访问的url对应的权限id 是否在权限列表的id中
				if !res.HasPermission {
					c.String(200, "没有权限")
					c.Abort()
				}

				//获取当前角色拥有的权限,并把权限id放在一个map对象中
				//roleAccess := []models.RoleAccess{}
				//models.DB.Where("role_id = ?", userinfoStruct[0].RoleId).Find(&roleAccess)
				//roleAccessMap := make(map[int]int)
				//for _, v := range roleAccess {
				//	roleAccessMap[v.AccessId] = v.AccessId
				//}
				实例化access
				//access := models.Access{}
				查询权限id
				//models.DB.Where("url = ? ", urlPath).Find(&access)
				判断权限id是否在角色对应的权限中
				//if _, ok := roleAccessMap[access.Id]; !ok {
				//	c.String(http.StatusOK, "没有权限")
				//	c.Abort() // 终止程序
				//}
			}
		}
	} else {
		//4、如果Session不存在,判断当前访问的URl是否是login doLogin captcha,如果不是跳转到登录页面,如果是不行任何操作
		//说明用户没有登录
		//需要排除到不需要做权限判断的路由
		if pathname != "/admin/login" && pathname != "/admin/dologin" && pathname != "/admin/captcha" {
			//跳转到登录页面
			c.Redirect(http.StatusFound, "/admin/login")
		}
	}
}

//排除权限判断的方法
func excludeAuthPath(urlPath string) bool {
	//加载配置文件
	cfg, err := ini.Load("./conf/app.ini")
	if err != nil {
		fmt.Printf("Fail to read file: %v", err)
		os.Exit(1)
	}
	//获取需要排除的地址
	excludeAuthPath := cfg.Section("").Key("excludeAuthPath").String()
	//拆分字符串成为一个切片
	excludeAuthPathSlice := strings.Split(excludeAuthPath, ",")
	//判断传入的地址是否在排除地址内
	for _, v := range excludeAuthPathSlice {
		if v == urlPath {
			return true
		}
	}
	return false
}

 (3). Verify that the above microservice method is correct

Start consul and various microservices, as well as projects, log in to the background, perform permission access, and find that the microservice method is no problem

3. Rbac microservice database extraction 

1. Extract rbac-related data tables

The database currently used by the project is the same database: ginshop , and the database configuration of the rbac microservice can be found in the rbac/conf/ app.ini configuration file under the server . The relevant configuration is as follows:

app_name   = rbac
# possible values: DEBUG, INFO, WARNING, ERROR, FATAL

[mysql]
ip       = 127.0.0.1
port     = 3306
user     = root
password = 123456
database = ginshop

[consul]
addr   = localhost:8082

Therefore, here is an example to illustrate the extraction of the database : extract the rbac microservice-related data tables , create a new database ginshoprbac , and then extract the rbac-related data tables (access, manager, role, role_access) to In the ginshoprbac database, of course, before extracting the data table, you must remember to backup 

 2. Modify the app.ini configuration

If the rbac-related database is extracted, then the data configuration app.ini is required. The modified configuration is as follows:

app_name   = rbac
# possible values: DEBUG, INFO, WARNING, ERROR, FATAL

[mysql]
ip       = 127.0.0.1
port     = 3306
user     = root
password = 123456
database = ginshoprbac

[consul]
addr   = localhost:8082

 3. Delete the client rbac related model

Because the rbac microservice is used, the model in the original project client is useless. Delete the useless model, and then test whether the function of the rbac microservice is correct. Here, delete the access.go and role in the model under the client . go, roleAccess.go , modify manager.go (manager.go model is still in use) , the modified manager.go code is as follows :

package models

//管理员表

type Manager struct { // 结构体首字母大写, 和数据库表名对应, 默认访问数据表users, 可以设置访问数据表的方法
	Id  int
	Username string
	Password string
	Mobile string
	Email string
	Status int
	RoleId int
	AddTime int
	IsSuper int
}

 After the modification, restart the background client and the rbac micro-server, test, and find that there is no problem, indicating that there is no problem in extracting the rbac micro-service data table        

Well, here we go, the practical content related to project microservices is here, to view more articles, please see the homepage

[Previous section] wiefuw[golang gin framework] 45. Gin mall project - role permission association of background Rbac microservice after microservice actual combat

Guess you like

Origin blog.csdn.net/zhoupenghui168/article/details/132155715