[golang gin框架] 41.Gin商城项目-微服务实战之后台Rbac微服务(用户登录 、Gorm数据库配置单独抽离、 Consul配置单独抽离)

上一节抽离了captcha验证码功能,集成了验证码微服务功能,这一节来看看后台Rbac功能,并抽离其中的用户登录,管理员管理,角色管理,权限管理等功能作为微服务来调用

一.引入

后台操作从登录到后台首页,然后其中的管理员管理,角色管理,权限管理等功能可以抽离出来作为 一个Rbac微服务,因为他们都是共同关系的,并且使用人员也不是太多,当然,也可以每个管理功能单独作为一个微服务来进行操作

二.创建权限管理Rbac微服务服务端以及实现后台用户登录微服务

1.生成权限管理Rbac微服务代码

在server目录下运行: go-micro new service rbac,生成 rbac微服务服务端代码

2.编写proto/rbac.proto文件,实现用户登录微服务逻辑

在这个文件中编写 用户登录相关代码,可参考: [golang gin框架] 13.Gin 商城项目-配置公共基类实现公共的成功,失败提示页面 用户登录、退出登录、以及权限判断
参考代码 controllers/admin/loginController.go如下:
//执行登录操作
func (con LoginController) DoIndex(c *gin.Context) {//获取表单中的数据captchaId := c.PostForm("captchaId")     // 验证码idverifyValue := c.PostForm("verifyValue") //验证码的值//获取用户名以及密码username := c.PostForm("username")password := c.PostForm("password")// 1.判断验证码是否验证成功: 这里调用的是上一节验证码微服务的功能if flag := models.VerifyCaptcha(captchaId, verifyValue); flag {//2.查询数据库,判断用户以及密码是否正确userinfo := []models.Manager{}password = models.Md5(password)models.DB.Where("username = ? and password = ? ", username, password).Find(&userinfo)if len(userinfo) > 0 {//3.执行登录,保存用户信息,执行跳转操作session := sessions.Default(c)//注意: session.Set没法保存结构体对应的切片,所以需要把结构体转换成json字符串userinfoSlice, _ := json.Marshal(userinfo)session.Set("userinfo_admin", string(userinfoSlice))session.Save()con.Success(c, "登录成功", "/admin")} else {con.Error(c, "用户名或密码错误", "/admin/login")}} else {con.Error(c, "验证码验证失败", "/admin/login")}
}

从上面可以看出:在权限管理Rbac微服务中要实现:

//2.查询数据库,判断用户以及密码是否正确
userinfo := []models.Manager{}
password = models.Md5(password)
models.DB.Where("username = ? and password = ? ", username, password).Find(&userinfo)

而实现上面的逻辑,则需要连接数据库,创建数据模型,这里使用GORM方式

(1).创建数据模型

在models下创建manager.go,可参考[golang gin框架] 13.Gin 商城项目-配置公共基类实现公共的成功,失败提示页面 用户登录、退出登录、以及权限判断

package models//管理员表type Manager struct { // 结构体首字母大写, 和数据库表名对应, 默认访问数据表users, 可以设置访问数据表的方法Id  intUsername stringPassword stringMobile stringEmail stringStatus intRoleId intAddTime intIsSuper int
}//配置数据库操作的表名称
func (Manager) TableName() string {return "manager"
}

(2).创建conf/app.ini文件

在微服务项目Rbac下创建conf/app.ini配置文件,一些配置,如:数据库配置,redis配置,consul配置信息都可以放到该文件下,以便使用,使用了这个文件下的配置,改变里面的数据不用重启项目,具体参考:[golang gin框架] 9.Gin GORM 中使用事务以及go-ini加载.ini配置文件

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]
#指定微服务的ip,一般一个微服务对应一台服务器,当在同一台服务器上有多个微服务时,以不同端口区分
addr   = localhost:8082

(3).定义initInt.go文件

在models下创建initInt.go文件,自动初始化app.ini,很多地方调用app.ini时,就可以从这里介入,该文件目的是减少代码的复用

package models//自动初始化app.ini:这里很多地方都要用到import ("fmt""os""gopkg.in/ini.v1"
)var Config *ini.File
var iniErr errorfunc init() {Config, iniErr = ini.Load("./conf/app.ini")if iniErr != nil {fmt.Printf("Fail to read file: %v", iniErr)os.Exit(1)}
}

 (4).创建initMysql.go

在models下创建initMysql.go文件,该文件目的是创建mysql数据库连接引擎

package models//https://gorm.io/zh_CN/docs/connecting_to_the_database.html
//微服务项目中: 推荐一个微服务对应一个数据库
import ("fmt""gorm.io/driver/mysql""gorm.io/gorm"
)var DB *gorm.DB
var err errorfunc init() {//读取.ini里面的数据库配置,相关配置从initIni.go中读取ip := Config.Section("mysql").Key("ip").String()port := Config.Section("mysql").Key("port").String()user := Config.Section("mysql").Key("user").String()password := Config.Section("mysql").Key("password").String()database := Config.Section("mysql").Key("database").String()// dsn := "root:123456@tcp(192.168.0.6:3306)/gin?charset=utf8mb4&parseTime=True&loc=Local"dsn := fmt.Sprintf("%v:%v@tcp(%v:%v)/%v?charset=utf8mb4&parseTime=True&loc=Local", user, password, ip, port, database)DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{QueryFields: true, //打印sql//SkipDefaultTransaction: true, //禁用事务})// DB.Debug()if err != nil {fmt.Println(err)}
}

 (5).编写proto/rbac.proto文件

编写proto/rbac.proto文件,实现微服务相关数据逻辑,可参考:[golang gin框架] 39.Gin商城项目-微服务实战之微服务架构

syntax = "proto3";package rbac;option go_package = "./proto/rbac";service Rbac {//登录操作rpc Login(LoginRequest) returns (LoginResponse) {}
}//用户信息model:参考models/manager.go,一一对应
message ManagerModel{int64 id=1;string username=2;string password=3;string mobile=4;string email=5;int64 status=6;int64 roleId=7;int64 addTime=8;int64 isSuper=9;
}//登录请求参数
message LoginRequest{string username=1;string password=2;
}//登录返回参数
message LoginResponse{bool isLogin=1;repeated ManagerModel userlist=2;  //因为在client端需要返回用户相关信息userinfo,故定义一个切片
}

(6).生成proto相关文件

参考[golang 微服务] 7. go-micro框架介绍,go-micro脚手架,go-micro结合consul搭建微服务案例,windows下运行 Makefile里面的proto下的代码 :protoc --proto_path=. --micro_out=. --go_out=:. proto/captcha.proto, 当然,如果是初次使用go-micro,则还需运行init下面的代码(@go xxx),引入相关包

   

(7).初始化服务端项目

初始化项目,引入项目所需要的包

go mod init rbac
go mod tidy

如果出现:

F:\www\go-data\src\go_code\micro\shop\server\rbac>go mod tidy
go: finding module for package go-micro.dev/v4/client
go: finding module for package gopkg.in/ini.v1
go: finding module for package go-micro.dev/v4
go: finding module for package go-micro.dev/v4/logger
go: finding module for package go-micro.dev/v4/server
go: finding module for package gorm.io/gorm
go: finding module for package gorm.io/driver/mysql
go: finding module for package go-micro.dev/v4/api
go: finding module for package google.golang.org/protobuf/proto
go: finding module for package google.golang.org/protobuf/reflect/protoreflect
go: finding module for package google.golang.org/protobuf/runtime/protoimpl
go: found go-micro.dev/v4 in go-micro.dev/v4 v4.10.2
go: found go-micro.dev/v4/logger in go-micro.dev/v4/logger v1.18.0
go: found gopkg.in/ini.v1 in gopkg.in/ini.v1 v1.67.0
go: found gorm.io/driver/mysql in gorm.io/driver/mysql v1.5.1
go: found gorm.io/gorm in gorm.io/gorm v1.25.2
go: found go-micro.dev/v4/api in go-micro.dev/v4/api v1.18.0
go: found go-micro.dev/v4/client in go-micro.dev/v4/client v1.18.0
go: found go-micro.dev/v4/server in go-micro.dev/v4/server v1.18.0
go: found google.golang.org/protobuf/proto in google.golang.org/protobuf v1.31.0
go: found google.golang.org/protobuf/reflect/protoreflect in google.golang.org/protobuf v1.31.0
go: found google.golang.org/protobuf/runtime/protoimpl in google.golang.org/protobuf v1.31.0
go: rbac/proto/rbac importsgo-micro.dev/v4/api: go-micro.dev/v4/api@v1.18.0: parsing go.mod:module declares its path as: github.com/micro/go-microbut was required as: go-micro.dev/v4/api

说明下载"go-micro.dev/v4"这个包失败了,这时则需运行命令 go get go-micro.dev/v4,如图:

 然后再次执行go mod tidy就可以了,这样项目中import包就会引入,不会变红

(8).编写handler/rbac.go用户登录微服务逻辑

因为要实现

//2.查询数据库,判断用户以及密码是否正确
userinfo := []models.Manager{}
password = models.Md5(password)
models.DB.Where("username = ? and password = ? ", username, password).Find(&userinfo)

所以在handler/rbac.go 中需要返回用户相关信息,实现用户登录逻辑代码如下:

package handlerimport ("context""rbac/models"pb "rbac/proto/rbac"
)type Rbac struct{}//后台用户登录的微服务
func (e *Rbac) Login(ctx context.Context, req *pb.LoginRequest, res *pb.LoginResponse) error {managerList := []models.Manager{}err := models.DB.Where("username=? AND password=?", req.Username, req.Password).Find(&managerList).Error//处理数据var templist []*pb.ManagerModelfor i := 0; i < len(managerList); i++ {templist = append(templist, &pb.ManagerModel{Id:       int64(managerList[i].Id),Username: managerList[i].Username,Password: managerList[i].Password,Mobile:   managerList[i].Mobile,Email:    managerList[i].Email,Status:   int64(managerList[i].Status),RoleId:   int64(managerList[i].RoleId),AddTime:  int64(managerList[i].AddTime),IsSuper:  int64(managerList[i].IsSuper),})}if len(managerList) > 0 {res.IsLogin = true} else {res.IsLogin = false}res.Userlist = templistreturn err
}

(9).配置consul服务发现 

在main.go配置consul服务发现

package mainimport ("rbac/handler""rbac/models"pb "rbac/proto/rbac""go-micro.dev/v4""go-micro.dev/v4/logger""github.com/go-micro/plugins/v4/registry/consul"
)var (service = "rbac"version = "latest"
)func main() {//集成consulconsulReg := consul.NewRegistry()// Create service//读取.ini里面的配置addr := models.Config.Section("consul").Key("addr").String()srv := micro.NewService(micro.Address(addr),  //指定微服务的ip:  选择注册服务器地址,也可以不配置,默认为本机,也可以选择consul集群中的clientmicro.Name(service),micro.Version(version),//注册consulmicro.Registry(consulReg),)srv.Init(micro.Name(service),micro.Version(version),)// Register handlerif err := pb.RegisterRbacHandler(srv.Server(), new(handler.Rbac)); err != nil {logger.Fatal(err)}// Run serviceif err := srv.Run(); err != nil {logger.Fatal(err)}
}

3.启动consul服务发现

在cmd中运行命令: consul agent -dev,具体参考:  [golang 微服务] 5. 微服务服务发现介绍,安装以及consul的使用,Consul集群

4.注册验证码微服务服务端到服务发现(consul)

rbac目录下运行go run main.go,然后在consul UI 查看,是否注册成功

注册成功了 

 三.创建权限管理Rbac微服务客户端

1.首先把server/rbac/proto文件夹复制到项目中

2.配置consul服务发现

在models下创建initRbacConsul.go,配置consul服务发现,以便调用,代码如下:

package models//Rbac consul(服务发现)初始化配置
//微服务客户端配置: 初始化consul配置,当一个项目中多个微服务时,就很方便了
//建议:一个微服务对应一个客户端,这样好管理import ("github.com/go-micro/plugins/v4/registry/consul""go-micro.dev/v4""go-micro.dev/v4/client""go-micro.dev/v4/registry"
)//RbacClient: 全局变量 在外部的包中可以调用
var RbacClient client.Client//init 方法: 当程序运行时就会自动执行
func init() {consulRegistry := consul.NewRegistry(//指定微服务的ip:  选择注册服务器地址,默认为本机,也可以选择consul集群中的client,建议一个微服务对应一个consul集群的clientregistry.Addrs("127.0.0.1:8500"),)// Create servicesrv := micro.NewService(micro.Registry(consulRegistry),)srv.Init()RbacClient = srv.Client()
}

 在这里,也许没有引入,执行命令:go mod tidy引入对应的包

3.调用Rbac微服务 

controllers/login.goDoIndex方法中调用Rbac微服务 

原DoIndex方法代码如下: 


//执行登录操作
func (con LoginController) DoIndex(c *gin.Context) {//获取表单中的数据captchaId := c.PostForm("captchaId")     // 验证码idverifyValue := c.PostForm("verifyValue") //验证码的值//获取用户名以及密码username := c.PostForm("username")password := c.PostForm("password")// 1.判断验证码是否验证成功if flag := models.VerifyCaptcha(captchaId, verifyValue); flag {//2.查询数据库,判断用户以及密码是否正确userinfo := []models.Manager{}password = models.Md5(password)models.DB.Where("username = ? and password = ? ", username, password).Find(&userinfo)if len(userinfo) > 0 {//3.执行登录,保存用户信息,执行跳转操作session := sessions.Default(c)//注意: session.Set没法保存结构体对应的切片,所以需要把结构体转换成json字符串userinfoSlice, _ := json.Marshal(userinfo)session.Set("userinfo_admin", string(userinfoSlice))session.Save()con.Success(c, "登录成功", "/admin")} else {con.Error(c, "用户名或密码错误", "/admin/login")}} else {con.Error(c, "验证码验证失败", "/admin/login")}
}

 然后在//2.查询数据库,判断用户以及密码是否正确这一步调用Rbac微服务,代码修改如下:

//这里需要import (
//     "context"
//	 pbRbac "goshop/proto/rbac"
//    )//执行登录操作
func (con LoginController) DoIndex(c *gin.Context) {//获取表单中的数据captchaId := c.PostForm("captchaId")     // 验证码idverifyValue := c.PostForm("verifyValue") //验证码的值//获取用户名以及密码username := c.PostForm("username")password := c.PostForm("password")// 1.判断验证码是否验证成功if flag := models.VerifyCaptcha(captchaId, verifyValue); flag {//2.查询数据库,判断用户以及密码是否正确//userinfo := []models.Manager{}//password = models.Md5(password)//models.DB.Where("username = ? and password = ? ", username, password).Find(&userinfo)//调用Rbac微服务rbacClient := pbRbac.NewRbacService("rbac", models.RbacClient)res, _ := rbacClient.Login(context.Background(), &pbRbac.LoginRequest{Username: username,Password: models.Md5(password),})//通过Rbac微服务结果,判断是否登录if res.IsLogin {//3.执行登录,保存用户信息,执行跳转操作session := sessions.Default(c)//注意: session.Set没法保存结构体对应的切片,所以需要把结构体转换成json字符串userinfoSlice, _ := json.Marshal(res.Userlist)  //res.Userlist:微服务返回的用户信息session.Set("userinfo_admin", string(userinfoSlice))session.Save()con.Success(c, "登录成功", "/admin")} else {con.Error(c, "用户名或密码错误", "/admin/login")}} else {con.Error(c, "验证码验证失败", "/admin/login")}
}

好了,权限管理Rbac微服务服客户端代码就ok了,接下来验证Rbac微服务是否成功

四.校验权限管理Rbac微服务功能

1.先启动服务端

见 [golang gin框架] 40.Gin商城项目-微服务实战之Captcha验证码微服务代码, 这里还要启动验证码captcha微服务服务端代码才行

2.启动客户端

在项目根目录下运行 :go run main.go,启动项目

3.校验权限管理Rbac微服务操作是否成功 

访问后台登录页面,输入用户名,密码,验证码,看看是否成功 

 

 好了,权限管理Rbac微服务后台用户登录功能客户端操作完成,这里微服务操作的服务端,客户端功能大致与[golang gin框架] 40.Gin商城项目-微服务实战之Captcha验证码微服务类似,可参考该文章操作,下面一节继续讲解权限管理Rbac微服务的角色增删改查微服务功能

 [上一节][golang gin框架] 40.Gin商城项目-微服务实战之Captcha验证码微服务

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/5446.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python实战

官方文档 请点击下面工程名称&#xff0c;跳转到代码的仓库页面&#xff0c;将工程 下载下来 Demo Code 里有详细的注释 LearnPythonPython 实现功能点demo

OpenCV for Python 实战(一):获取图片拍摄GPS地址并自动添加水印

Hello 我们在OpenCV每天的基础博客当中已经更新了很多了&#xff0c;那么今天我们就来结合前几天的内容。做一个获取属性然后添加对应属性的水印。那让我们赶快开始吧~ 文章目录 图片EXIFPython 获取EXIFexifread库使用方法转换成文字地址 添加水印cv2.putText() 每日总结 图片…

【001 操作系统】什么是线程、进程?线程进程的区别是什么?

一、什么是线程、进程&#xff1f; 进程&#xff1a;进程是资源分配的基本单位&#xff0c;它是程序执行时的一个实例&#xff0c;在程序运行时创建。 在Linux环境下&#xff0c;每个进程有自己各自独立的 4G 地址空间&#xff0c;大家互不干扰对方&#xff0c;如果两个进程之间…

基于大模型的Text2SQL微调的实战教程

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

Homography单应性矩阵

1. Homography 单应性概念 考虑 同一个平面(比如书皮)的两张图片&#xff0c;红点表示同一个物理坐标点在两张图片上的各自位置。在 CV 术语中&#xff0c;我们称之为对应点。 Homography 就是将一张图像上的点映射到另一张图像上对应点的3x3变换矩阵. 因为 Homography 是一个 …

Python模块requests基本用法

简介 Python 的 requests 模块是一个流行的第三方库&#xff0c;用于发送HTTP请求。它提供了一组简洁且易于使用的API&#xff0c;使得在Python中进行网络通信变得更加简单和灵活。 目录 1. 基本概念 1.1. HTTP 协议 1.2. GET 请求 1.3. POST 请求 1.4. get 和 post 的区别…

java本地socket服务端暴露至公网访问【内网穿透】

前言 &#x1f4d5;作者简介&#xff1a;热爱跑步的恒川&#xff0c;致力于C/C、Java、Python等多编程语言&#xff0c;热爱跑步&#xff0c;喜爱音乐的一位博主。 &#x1f4d7;本文收录于恒川的日常汇报系列&#xff0c;大家有兴趣的可以看一看 &#x1f4d8;相关专栏C语言初…

蓝桥杯专题-真题版含答案-【生命之树】【消除尾一】【密码脱落】【生日蜡烛】

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 &#x1f449;关于作者 专注于Android/Unity和各种游…

【Java项目实战-牛客社区】--idea maven配置

第一 IDEA集成Maven插件&#xff0c;并配置Maven 以下步骤中&#xff0c;重点关注红色方框的配置 第二 IDEA 创建 Maven 项目 步骤一&#xff1a;创建模块&#xff0c;选择Maven&#xff0c;点击Next 步骤二&#xff1a;填写模块名称&#xff0c;坐标信息&#xff0c;点击finis…

【技术面试】Java八股文业余选手-下篇(持续更新)

文章目录 5. RocketMQ 消息中间件、RabbitMQ、ActiveMQ【√】5.1 RocketMQ 6. Kafka 大数据量消息中间件、ElasticSearch、ZooKeeper【√】6.1 Kafka【√】6.2 ElasticSearch 7. 分布式、研发提效、高并发、线程安全【√】7.1 分布式与集群【√】7.2 高并发、线程安全【】7.3 研…

【JavaScript】实现网页中的选项卡

一、简易选项卡 以下是实现一个简单选项卡的代码。代码中有注释。 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0"…

Airbnb 引入 HTTP Streaming,网页性能得到大幅度提升

Airbnb 通过引入HTTP Streaming来提升网站的页面加载性能。他们将测试的每个页面&#xff08;包括主页&#xff09;的首次内容绘制&#xff08;First Contentful Paint&#xff0c;FCP&#xff09;时间降低了大约 100 毫秒。他们还最小化了后端慢查询对加载时间的影响。 Airbn…

Docker概述 镜像-容器基本操作

Docker 概述 Docker是一个开源的应用容器引擎&#xff0c;基于go语言开发并遵循了apache2.0协议开源。 Docker是在Linux容器里运行应用的开源工具&#xff0c;是一种轻量级的“虚拟机”。 Docker 的容器技术可以在一台主机上轻松为任何应用创建一个轻量级的、可移植的、自给自足…

Docker 安装 和 GPU 支持

一、Docker安装过程&#xff08;ubuntu18.04环境&#xff09; 清华镜像 docker 安装&#xff1a;docker-ce | 镜像站使用帮助 | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 1、由于apt官方库里的docker版本可能比较旧&#xff0c;所以先卸载可能存在的旧版本&…

MySQL(一)基本架构、SQL语句操作、试图

MySQL系列文章 MySQL&#xff08;一&#xff09;基本架构、SQL语句操作、试图 MySQL&#xff08;二&#xff09;索引原理以及优化 MySQL&#xff08;三&#xff09;SQL优化、Buffer pool、Change buffer MySQL&#xff08;四&#xff09;事务原理及分析 MySQL&#xff08;五&a…

异步任务——CompletabelFuture

本专栏学习内容又是来自尚硅谷周阳老师的视频 有兴趣的小伙伴可以点击视频地址观看 在学习CompletableFuture之前&#xff0c;必须要先了解一下Future Future 概念 Future接口&#xff08;FutureTask实现类&#xff09;定义了操作异步任务执行的一些方法&#xff0c;如获取异…

前端学习——Vue (Day2)

指令补充 指令修饰符 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevi…

每月进度总结 7月1日~7月22日

一个月已经过了三分之二了&#xff0c;感觉这个月是在学校学的很多。也是最充实的三个星期。其中也有发呆&#xff0c;也有过懊悔&#xff0c;今天状态为什么这么差&#xff0c;就学了这一点。但是还有学到知识的喜悦。总之是认识到了自己的很多不足&#xff0c;也找到了相对正…

【笔试强训选择题】Day28.习题(错题)解析

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;笔试强训选择题 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01;&#xff…

基础 | 日志 | 体系介绍

INDEX 总览图上图的说明 总览图 上图的说明 日志体系的结构大约可以概括为 日志门面日志绑定层日志实现日志桥接层 slf4j 是 日志门面&#xff0c;所谓日志门面可以理解为日志总接口 slf4j-log4j、log4j-slf4j-impl 是 日志绑定层&#xff0c;日志绑定层的作用是将 日志门面…