[golang gin框架] 46.Gin商城项目-微服务实战之后台Rbac客户端调用微服务权限验证以及Rbac微服务数据库抽离

一. 根据用户的权限动态显示左侧菜单微服务

1.引入

后台Rbac客户端调用微服务权限验证功能主要是: 登录后显示用户名称、根据用户的权限动态显示左侧菜单,判断当前登录用户的权限 、没有权限访问则拒绝,参考[golang gin框架] 14.Gin 商城项目-RBAC管理,该微服务功能和上一节[golang gin框架] 45.Gin商城项目-微服务实战之后台Rbac微服务之角色权限关联功能是一样的 ,因为controllers/admin/mainController.go的Index()方法都是要获取所有权限列表,以及当前角色拥有的权限,代码如下:

Go 复制代码
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. 完善handler/rbacRole.go下的**RoleAuth()**方法

上面的代码和上一节的handler/rbacRole.go下的RoleAuth() 方法类似,差别在于上面有排序功能,把上面排序的代码替换微服务RoleAuth()中对应的代码,然后在controllers/admin/mainController.go的Index()方法中调用一下这个微服务的RoleAuth()方法就可以了,替换后,handler/rbacRole.go下的**RoleAuth()**方法代码如下:

Go 复制代码
//授权
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. controllers/admin/mainController.go的Index()调用微服务的RoleAuth()方法,判断是否显示对应的菜单

然后在controllers/admin/mainController.go的Index()方法中调用一下这个微服务的RoleAuth()方法,代码如下:

Go 复制代码
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")
	}
}

经过验证,发现没问题,这里就不再说明了,因为微服务RoleAuth()方法基本上没有发生变化,只是后台mainControllers.go的Index方法调用了而已

二.权限判断: 没有登录的用户不能进入后台管理中心

1.抽离adminAuth.go中间件代码,做成一个微服务方法

(1).proto/rbacRole.proto增加rpc MiddlewaresAuth方法

这里的权限判断: 没有登录的用户不能进入后台管理中心功能以前是放在middlewares/adminAuth.go中间件 里面进行判断的,现在,把里面的逻辑代码抽离出来,做成一个微服务,先来看看adminAuth.go中间件 里面的代码:

Go 复制代码
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
}

从上面代码中,可以看出:当用户登录成功后,才需要判断要访问的url对应的权限id是否在对应角色的权限中,故构建微服务方法时,需要传入要访问的urlPath,以及角色id,这里把该微服务方法放到rbacRole这个微服务中,所以,在server端的proto/rbacRole.proto下的service RbacRole下增加rpc方法,如下:

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

然后实现上面rpc方法:

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

完整代码如下:

Go 复制代码
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).更新proto文件夹下对应rbacRole的方法

运行命令protoc --proto_path=. --micro_out=. --go_out=:. proto/rbacRole.proto更新proto下的文件

(3).handler/rbacRole.go下实现上面的rpc MiddlewaresAuth方法

把中间件middlewares/adminAuth.go中 判断用户权限相关代码抽离出来,做成一个MiddlewaresAuth()微服务方法,代码如下:

Go 复制代码
//权限判断
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.项目端中间件adminAuth.go调用上面微服务方法,进行权限判断

(1).复制server端proto下rbacRole.go以及rbacRole文件夹到项目的proto下

因为修改了server中的rbacRole.proto,需要同步

(2).在项目的middlewares/adminAuth.go中间件中调用权限判断微服务方法

Go 复制代码
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).验证上面的微服务方法是否正确

启动consul以及各个微服务,以及项目,登录后台,进行权限访问,发现该微服务方法没问题

三. Rbac微服务数据库抽离

1.抽离rbac相关数据表

目前项目使用的数据库是同一个数据库:ginshop,rbac微服务的数据库配置见server下rbac/conf/app.ini配置文件,相关配置如下:

bash 复制代码
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

所以,这里举例说明抽离数据库:把rbac微服务相关数据表抽离出来,独立一个数据库,创建一个新的数据库ginshoprbac ,然后把rbac相关的数据表 (access,manager,role,role_access)抽离到ginshoprbac数据库中,当然,在抽离数据表之前,一定要记得备份

2.修改app.ini配置

抽离了rbac相关数据库,那么就要数据配置app.ini,修改后的配置如下:

bash 复制代码
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.删除客户端rbac相关model

因为使用的是rbac微服务了,所以原来项目客户端中的model就没用了,删除无用的model,然后测试rbac微服务功能是否正确,这里删除client下model中的access.go,role.go,roleAccess.go ,修改manager.go(manager.go模型还在使用) ,修改后的manager.go代码如下**:**

Go 复制代码
package models

//管理员表

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

修改完后,重启后台客户端,以及rbac微服务端,测试,发现没有问题,说明抽离rbac微服务数据表没有问题

好了,到这里,项目微服务相关实战内容就到这里了,查看更多文章,请看主页

上一节\][wiefuw\[golang gin框架\] 45.Gin商城项目-微服务实战之后台Rbac微服务之角色权限关联](https://blog.csdn.net/zhoupenghui168/article/details/132115181 "wiefuw[golang gin框架] 45.Gin商城项目-微服务实战之后台Rbac微服务之角色权限关联")

相关推荐
luckys.one38 分钟前
第9篇:Freqtrade量化交易之config.json 基础入门与初始化
javascript·数据库·python·mysql·算法·json·区块链
言之。2 小时前
Django中的软删除
数据库·django·sqlite
是誰萆微了承諾4 小时前
【golang学习笔记 gin 】1.2 redis 的使用
笔记·学习·golang
阿里嘎多哈基米4 小时前
SQL 层面行转列
数据库·sql·状态模式·mapper·行转列
抠脚学代码4 小时前
Ubuntu Qt x64平台搭建 arm64 编译套件
数据库·qt·ubuntu
jakeswang4 小时前
全解MySQL之死锁问题分析、事务隔离与锁机制的底层原理剖析
数据库·mysql
Heliotrope_Sun4 小时前
Redis
数据库·redis·缓存
一成码农4 小时前
MySQL问题7
数据库·mysql
吃饭最爱4 小时前
JUnit技术的核心和用法
数据库·oracle·sqlserver
专注API从业者5 小时前
Python/Java 代码示例:手把手教程调用 1688 API 获取商品详情实时数据
java·linux·数据库·python