[golang gin Framework] 45. ジンモールプロジェクト - マイクロサービス実戦後のバックグラウンドRbacマイクロサービスの役割許可関連付け

ロールとパーミッションの関係については前回の記事で説明しています。[golang gin Framework]を参照してください。 14. Gin mall プロジェクト - RBAC 管理ロールとパーミッションの関連付け、ロール認可、ここではロールからパーミッションへの認可操作がマイクロサービスを通じて実現されており、ここで実装する機能は 2 つあり、1 つは承認の入力、もう 1 つは送信操作の承認です。ページは次のとおりです。

 1.バックグラウンド権限管理Rbacのロール権限関連付けマイクロサービスサーバー機能を実現

ここでは、proto/rbacRole.proto に認可オペレーション Auth()と認可オペレーション DoAuth() の 2 つのメソッドを追加する必要があります。詳細は、[golang gin Framework] 14.Gin Mall プロジェクト - RBAC Management_Role 権限管理 認可メソッドの追加を参照してください。 、元のコードは次のとおりです。

//授权
func (con RoleController) Auth(c *gin.Context) {
	//获取id
	id, err := models.Int(c.Query("id"))
	if err != nil {
		con.Error(c, "传入数据错误", "/admin/role")
		return
	}
	role := models.Role{Id: id}
	models.DB.Find(&role)

	//获取所有权限列表
	accessList := []models.Access{}
	models.DB.Where("module_id = ?", 0).Preload("AccessItem").Find(&accessList)

	//获取当前角色拥有的权限,并把权限id放在一个map对象中
	roleAccess := []models.RoleAccess{}
	models.DB.Where("role_id = ?", id).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/role/auth.html", gin.H{
		"roleId":     id,
		"accessList": accessList,
	})
}

//授权提交
func (con RoleController) DoAuth(c *gin.Context) {
	//获取提交的表单数据
	roleId, err := models.Int(c.PostForm("role_id"))
	if err != nil {
		con.Error(c, "传入数据错误", "/admin/role")
		return
	}
	//获取表单提交的权限id切片
	accessIds := c.PostFormArray("access_node[]")
	//先删除当前角色对应的权限
	roleAccess := models.RoleAccess{}
	models.DB.Where("role_id = ?", roleId).Delete(&roleAccess)

	//循环遍历accessIds,增加当前角色对应的权限
	for _, v := range accessIds {
		roleAccess.RoleId = roleId
		accessId, _ := models.Int(v)
		roleAccess.AccessId = accessId
		models.DB.Create(&roleAccess)
	}

	con.Success(c, "角色授权成功", "/admin/role")
}

 1. Auth() および DoAuth() メソッド関連のコードを proto/rbacRole.proto に追加します。

上記のメソッドを参照して、Auth()およびDoAuth()関連のメソッド コードを、ロール microservice のプロト内サービス 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) {}
}

ここでは、ロール認可リクエスト メソッドRoleAuthRequest()と、ロール認可リクエスト レスポンス メソッドRoleAuthResponse( )を実装する必要があります。上記の Auth() メソッドを通じて、ロール ID roleId を RoleAuthRequest() に渡す必要があるかどうかを判断できます。要求すると、アクセス許可スライスが応答メソッドで返されます。これは、メッセージ AccessModelを構築する必要があります。コードは次のとおりです。

//权限相关模型:参考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 RoleAuthRequest{
	int64 roleId=1;
}
//角色授权响应参数
message RoleAuthResponse{
	repeated AccessModel accessList=1;
}

ロール承認送信リクエスト メソッドRoleDoAuthRequest()とロール承認送信リクエスト レスポンス メソッド roleDoAuthResponse() を実装するには、上記の Auth() メソッドを通じて、ロール ID roleIdロールの対応するパーミッション ID スライスを決定できます。これは、RoleDoAuthRequest リクエストで渡され、応答メソッドで返される必要があります。操作が完了したかどうかに関係なく、コードは次のとおりです。

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

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

 完全なコードは次のとおりです。

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) {}
}

//角色相关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;
}

2. rbacRole.protoをコンパイルします

rbacRole.proto が変更されているため、コマンドprotoc --proto_path=

3. handler/rbacRole.go ファイルで、新しく追加された Auth() メソッドと DoAuth() メソッドを実装します。

 実装する前に、 models :RoleAcces.go model:の下にロールと権限の関連付けモデルを導入する必要があります。

package models

//角色-权限 关联表

type RoleAccess struct {
	AccessId int
	RoleId   int
}

func (RoleAccess) TableName() string {
	return "role_access"
}

次に、Auth() メソッドと DoAuth() メソッドを実装します。[golang gin Framework] 14 を参照して ください。Gin mall プロジェクトと RBAC Management_role 権限の関連付けの Auth() メソッドと DoAuth メソッドを参照し、そこからコードを抽出し、handler/rbacRole に追加します。 .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").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
}

//执行授权
func (e *RbacRole) RoleDoAuth(ctx context.Context, req *pb.RoleDoAuthRequest, res *pb.RoleDoAuthResponse) error {
	//先删除当前角色对应的权限
	roleAccess := models.RoleAccess{}
	models.DB.Where("role_id = ?", req.RoleId).Delete(&roleAccess)

	//循环遍历accessIds,增加当前角色对应的权限
	for _, v := range req.AccessIds {
		roleAccess.RoleId = int(req.RoleId)
		accessId, _ :=strconv.Atoi(v)
		roleAccess.AccessId = accessId
		models.DB.Create(&roleAccess)
	}

	res.Success = true
	res.Message = "授权成功"
	return nil
}

4.バックグラウンド権限管理Rbacのロール権限関連付けマイクロサービスクライアント呼び出し機能を実現

rbacRole.proto ファイルが変更され、再コンパイルされたため、server/rbac/proto フォルダーの下にある rbacRole.go フォルダーと rbacRole フォルダーをクライアント プロジェクトの proto フォルダーにコピーする必要があります。

次に、 controllers/admin/roleController.go にAuth()を実装し、DoAuth() がロールと権限の関連付けマイクロサービス メソッドを呼び出します。最初に Auth() と DoAuth() の古いコードを削除してから、新しいロールを追加する必要があります-permission association マイクロサービス メソッドについては、記事の冒頭にある古いメソッドのコードを参照してください。新しいコードは次のとおりです。


//授权
func (con RoleController) Auth(c *gin.Context) {
	//获取id
	id, err := models.Int(c.Query("id"))
	if err != nil {
		con.Error(c, "传入数据错误", "/admin/role")
		return
	}
	role := models.Role{Id: id}
	models.DB.Find(&role)

	//调用微服务获取角色授权相关数据
	rbacClient := pbRbac.NewRbacRoleService("rbac", models.RbacClient)
	res, _ := rbacClient.RoleAuth(context.Background(), &pbRbac.RoleAuthRequest{
		RoleId: int64(id),
	})

	c.HTML(http.StatusOK, "admin/role/auth.html", gin.H{
		"roleId":     id,
		"accessList": res.AccessList,
	})
}

//授权提交
func (con RoleController) DoAuth(c *gin.Context) {
	//获取提交的表单数据
	roleId, err := models.Int(c.PostForm("role_id"))
	if err != nil {
		con.Error(c, "传入数据错误", "/admin/role")
		return
	}
	//获取表单提交的权限id切片
	accessIds := c.PostFormArray("access_node[]")
	//调用微服务执行授权
	rbacClient := pbRbac.NewRbacRoleService("rbac", models.RbacClient)
	res, _ := rbacClient.RoleDoAuth(context.Background(), &pbRbac.RoleDoAuthRequest{
		RoleId:    int64(roleId),
		AccessIds: accessIds,
	})

	if res.Success {
		con.Success(c, "角色授权成功", "/admin/role")
		return
	}
	con.Error(c, "授权失败", "/admin/role/auth?id="+models.String(roleId))
}

完全な roleController.go コードは次のとおりです。

package admin

import (
	"context"
	"github.com/gin-gonic/gin"
	"goshop/models"
	pbRbac "goshop/proto/rbacRole"
	"net/http"
	"strings"
)

type RoleController struct {
	BaseController
}

//角色列表
func (con RoleController) Index(c *gin.Context) {
	//调用Rbac微服务
	rbacClient := pbRbac.NewRbacRoleService("rbac", models.RbacClient)
	res, _ := rbacClient.RoleGet(context.Background(), &pbRbac.RoleGetRequest{})

	c.HTML(http.StatusOK, "admin/role/index.html", gin.H{
		"roleList": res.RoleList,
	})
}

//新增角色
func (con RoleController) Add(c *gin.Context) {
	c.HTML(http.StatusOK, "admin/role/add.html", gin.H{})
}

//新增角色:提交
func (con RoleController) DoAdd(c *gin.Context) {
	//获取表单的提交数据
	//strings.Trim(str, cutset), 去除字符串两边的cutset字符
	title := strings.Trim(c.PostForm("title"), " ") // 去除字符串两边的空格
	description := strings.Trim(c.PostForm("description"), " ")

	//判断角色名称是否为空
	if title == "" {
		con.Error(c, "角色名称不能为空", "/admin/role/add")
		return
	}

	//调用微服务,实现角色的添加
	rbacClient := pbRbac.NewRbacRoleService("rbac", models.RbacClient)
	res, _ := rbacClient.RoleAdd(context.Background(), &pbRbac.RoleAddRequest{
		Title:       title,
		Description: description,
		AddTime:     models.GetUnix(),
		Status:      1,
	})
	if !res.Success {
		con.Error(c, "增加角色失败 请重试", "/admin/role/add")
	} else {
		con.Success(c, "增加角色成功", "/admin/role")
	}
}

//编辑角色
func (con RoleController) Edit(c *gin.Context) {
	//获取角色id
	id, err := models.Int(c.Query("id"))
	if err != nil {
		con.Error(c, "传入数据错误", "/admin/role")
	} else {
		//调用微服务,获取角色信息
		rbacClient := pbRbac.NewRbacRoleService("rbac", models.RbacClient)
		res, _ := rbacClient.RoleGet(context.Background(), &pbRbac.RoleGetRequest{
			Id: int64(id),
		})
		c.HTML(http.StatusOK, "admin/role/edit.html", gin.H{
			"role": res.RoleList[0],
		})
	}
}

//编辑角色:提交
func (con RoleController) DoEdit(c *gin.Context) {
	//获取提交的表单数据
	id, err := models.Int(c.PostForm("id"))
	if err != nil {
		con.Error(c, "传入数据错误", "/admin/role")
		return
	}
	//获取表单的提交数据
	//strings.Trim(str, cutset), 去除字符串两边的cutset字符
	title := strings.Trim(c.PostForm("title"), " ") // 去除字符串两边的空格
	description := strings.Trim(c.PostForm("description"), " ")
	//判断角色名称是否为空
	if title == "" {
		con.Error(c, "角色名称不能为空", "/admin/role/add")
		return
	}
	//调用微服务修改
	rbacClient := pbRbac.NewRbacRoleService("rbac", models.RbacClient)
	res, _ := rbacClient.RoleEdit(context.Background(), &pbRbac.RoleEditRequest{
		Id:          int64(id),
		Title:       title,
		Description: description,
	})
	if !res.Success {
		con.Error(c, "修改数据失败", "/admin/role/edit?id="+models.String(id))
		return
	}
	con.Success(c, "修改数据成功", "/admin/role")
}

//删除角色
func (con RoleController) Delete(c *gin.Context) {
	//获取提交的表单数据
	id, err := models.Int(c.Query("id"))
	if err != nil {
		con.Error(c, "传入数据错误", "/admin/role")
		return
	}

	rbacClient := pbRbac.NewRbacRoleService("rbac", models.RbacClient)
	res, _ := rbacClient.RoleDelete(context.Background(), &pbRbac.RoleDeleteRequest{
		Id: int64(id),
	})
	if res.Success {
		con.Success(c, "删除数据成功", "/admin/role")
		return
	}
	con.Error(c, "删除数据失败", "/admin/role")
}

//授权
func (con RoleController) Auth(c *gin.Context) {
	//获取id
	id, err := models.Int(c.Query("id"))
	if err != nil {
		con.Error(c, "传入数据错误", "/admin/role")
		return
	}
	role := models.Role{Id: id}
	models.DB.Find(&role)

	//调用微服务获取角色授权相关数据
	rbacClient := pbRbac.NewRbacRoleService("rbac", models.RbacClient)
	res, _ := rbacClient.RoleAuth(context.Background(), &pbRbac.RoleAuthRequest{
		RoleId: int64(id),
	})

	c.HTML(http.StatusOK, "admin/role/auth.html", gin.H{
		"roleId":     id,
		"accessList": res.AccessList,
	})
}

//授权提交
func (con RoleController) DoAuth(c *gin.Context) {
	//获取提交的表单数据
	roleId, err := models.Int(c.PostForm("role_id"))
	if err != nil {
		con.Error(c, "传入数据错误", "/admin/role")
		return
	}
	//获取表单提交的权限id切片
	accessIds := c.PostFormArray("access_node[]")
	//调用微服务执行授权
	rbacClient := pbRbac.NewRbacRoleService("rbac", models.RbacClient)
	res, _ := rbacClient.RoleDoAuth(context.Background(), &pbRbac.RoleDoAuthRequest{
		RoleId:    int64(roleId),
		AccessIds: accessIds,
	})

	if res.Success {
		con.Success(c, "角色授权成功", "/admin/role")
		return
	}
	con.Error(c, "授权失败", "/admin/role/auth?id="+models.String(roleId))
}

 2. 検証権限管理 Rbacの役割権限関連付けマイクロサービス機能

[golang gin フレームワーク] 43. ジンモールプロジェクト - マイクロサービスの実戦後のバックグラウンド Rbac マイクロサービスの管理者の追加、削除、変更、クエリ、および管理者とロールの関連付けを参照

1. 最初にサーバーを起動します

[golang gin フレームワーク] 40. ジン モール プロジェクト - マイクロサービス戦闘で検証コード マイクロサービス コードをキャプチャ、ここでも検証コード キャプチャ マイクロサービス サーバーコードと権限管理 Rbac マイクロサービスを開始します(ユーザー ログイン マイクロサービスサーバー、ロール マイクロサービスサーバー、管理者を管理します)マイクロサービスサーバーを管理します)サーバー

 

2. クライアントを起動する

プロジェクトのルート ディレクトリで実行します。 go run main.go を実行してプロジェクトを開始します。

3. 権限管理 Rbac のロールと権限に関連付けられたマイクロサービス操作が成功したかどうかを確認します。 

バックグラウンドログインページにアクセスし、ユーザー名、パスワード、確認コードを入力し、バックグラウンドでログインし、ロール管理リストページに入り、ロールを承認します

 

 

以上で権限管理Rbacのロール権限関連付けマイクロサービス機能のクライアント操作が完了しましたので、マイクロサービスを呼び出すモールクライアントの権限検証とRbacマイクロサービスデータベース抽出機能の修正について説明します。

[前節] [golang gin フレームワーク] 44. ジンモールプロジェクト - マイクロサービスの実戦後のバックグラウンド Rbac マイクロサービスの追加、削除、変更、アクセス許可の確認

おすすめ

転載: blog.csdn.net/zhoupenghui168/article/details/132115181