#### 基于go-micro微服务的实战-Gateway网关层的鉴权-rbac(六)
***
**文章最后附带完整代码**
[上一节](https://blog.csdn.net/toegg/article/details/127181203?spm=1001.2014.3001.5501)讲了身份认证。这节就接着讲鉴权授权,也就是访问权限,身份认证通过后对其授权是否有权限访问,不同用户具有的访问选项不同。A能访问a,b,c链接,B能访问b,c,d。
这里用的是常用的Rbac模型,主要三个主体,**用户**,**角色**和**权限**。三个主体的关系概括一句话:**用户属于某个角色,某个角色具有某些权限**。
设计流程是这样
1. 权限的变更频率少,所以把角色权限,也就是角色对应权限放到缓存Redis中。
2. 采用定时任务cron,每分钟跑权限检测脚本
2.1 有变更标识则强制刷新权限缓存(在后台设置);
2.2 没变更则累计30分钟刷新一次权限缓存;
2.3 上面两种情况都不符合,则判断角色权限是否为空,权限是否为空,空则加载对应缓存
3. 用户登录的jwt自定义字段增加所属角色id**RoleId**
4. 网关层Gateway身份认证猴,解析jwt中**RoleId**来获取Redis缓存中的角色权限,判断是否具有对应权限。
##### 第一步:增加Rbac的数据表和结构体
创建Rbac的几张数据表,用户表之前已有,无需创建,直接用
```sql
CREATE TABLE `role` (
`role_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '角色id',
`name` varchar(50) NOT NULL COMMENT '角色名',
PRIMARY KEY (`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色表';
INSERT INTO `role` VALUES ('1', '普通用户');
INSERT INTO `role` VALUES ('2', '管理员');
CREATE TABLE `method` (
`id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '方法id',
`name` varchar(50) NOT NULL COMMENT '方法名',
`parent_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '所属微服务模块id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='方法权限表';
INSERT INTO `method` VALUES ('1', 'user.TestUser', '1');
INSERT INTO `method` VALUES ('2', 'user.UserReg', '1');
INSERT INTO `method` VALUES ('3', 'user.UserLogin', '1');
CREATE TABLE `role_method` (
`role_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '角色id',
`method_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '方法id',
PRIMARY KEY (`role_id`,`method_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色权限表';
INSERT INTO `role_method` VALUES ('1', '1');
INSERT INTO `role_method` VALUES ('1', '2');
INSERT INTO `role_method` VALUES ('1', '3');
CREATE TABLE `user_role` (
`user_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '用户id',
`role_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '角色id',
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户角色表';
INSERT INTO `user_role` VALUES ('43', '1');
//额外添加的,Rbac模型中只需上面4张
CREATE TABLE `service` (
`id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '微服务模块id',
`name` varchar(50) NOT NULL COMMENT '服务模块名',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='微服务模块表';
INSERT INTO `service` VALUES ('1', '用户服务模块');
```
创建完了表结构,需要把表结构也转化成Golang的结构体,方便gorm操作Db。这里推荐使用gorm的开源工具**gormt**[github.com/xxjwxc/gormt](https://github.com/xxjwxc/gormt), 可以将mysql数据库表结构自动生成golang sturct结构,带大驼峰命名规则。带json标签。
根据git上的安装步骤安装即可,我用的是window的可视化程序,直接下载使用。下载连接:[https://github.com/xxjwxc/gormt/releases](https://github.com/xxjwxc/gormt/releases)
安装完成之后,这里用的是window可视化工具,如果是编译安装,则用编译后的(gormt.exe或者gormt)打开工具(看git步骤)。
点击右上角的**set**配数据库等信息,点击**refresh**,就如下所示,可以直接复制struct,不符合预期则做修改即可,不用每个表都手动敲struct。把对应的Rbac结构体放到`grpc_server/user/models/user_model.go`模型中
##### 第二步:增加定时刷新Redis权限缓存的脚本
在`grpc_util中`目录中创建`rbac_handler`目录,目录下创建`rbac_handler.go`脚本
其中,Redis权限缓存的命名规则
```go
Redis的命名格式:
--角色对应权限用set集合存储
----格式key rbac_role_角色id
----格式val []string{方法id}
--服务方法用hash类型存储
----格式 key:rbac_method
---- field:rbac_method_方法名
---- val:方法id
```
脚本内容,只贴main部分,逻辑业务则没贴出来,上gitee看完整代码
```go
const(
KEY_RBAC_REFRESH = "rbac_handler_refresh" //强制刷新rbac的标识key
KEY_RBAC_REFRESH_TIMES = "rbac_handler_times" //累计cron执行检测次数key
KEY_RBAC_ROLE_PREFIX = "rbac_role_" //角色对应权限的key前缀
KEY_RBAC_METHOD = "rbac_method" //服务方法hash结构的key值
KEY_RBAC_METHOD_PREFIX = "rbac_method_" //服务方法hash结构的field前缀
)
func main(){
//创建Redis客户端
addr := fmt.Sprintf("%v:%d", REDIS_ADDR, REDIS_PORT)
redis := redis.NewClient(&redis.Options{Addr:addr})
defer redis.Close()
_, err := redis.Ping().Result()
if err != nil {
log.Println("err :", err)
return
}
//是否有强制刷新标识(在后台设置)
if redis.Get(KEY_RBAC_REFRESH).Val() == "1" {
if refresh_rbac_handler(redis) == nil {
redis.Del(KEY_RBAC_REFRESH)
}
return
}
//判断权限缓存中的方法缓存是否为空
if redis.HLen(KEY_RBAC_METHOD).Val() <= 0 {
refresh_rbac_methods(redis)
}
//判断权限缓存中的角色缓存是否为空,只判断角色1
if redis.SCard(KEY_RBAC_ROLE_PREFIX + "1").Val() <= 0{
refresh_rbac_role_methods(redis)
}
//30分钟则强制刷新一次权限缓存
if redis.Get(KEY_RBAC_REFRESH_TIMES).Val() == "30"{
if refresh_rbac_handler(redis)!= nil{
return
}
redis.Set(KEY_RBAC_REFRESH_TIMES, 1, 0)
}else{
redis.Incr(KEY_RBAC_REFRESH_TIMES)
}
}
```
执行脚本完成,把该脚本放入cron定时任务,1分钟执行一次监控检测
```go
# vi /etc/crontab
*/1 * * * * root /home/tool/golearn/src/emicro_6/grpc_util/rbac_handler/rbac_handler
```
##### 第三步:用户服务的注册接口和登录接口的调整
注册接口增加用户角色的记录,用**gorm**的事务操作Db
```go
//写进数据库
user.Pwd = utils.Md5(user.Pwd)
tx:= models.Db.Begin()
result := tx.Create(&user)
if result.Error != nil{
tx.Rollback()
return result.Error
}
userRole := models.UserRole{Id: user.Id, RoleId: common.DefaultRoleId}
result = tx.Create(&userRole)
if result.Error != nil{
tx.Rollback()
return result.Error
}
tx.Commit()
resp.Status = common.RESP_SUCCESS
resp.Msg = "success"
```
登录接口的调整,获取用户的角色,放到token中
```go
type result struct {
UserId int32
Pwd string
RoleId int32
}
var res result
models.Db.Table("user").Select("user.user_id, user.pwd, user_role.role_id").Joins("left join user_role on user.user_id = user_role.user_id").Where("user.phone = ?", req.Phone).Scan(&res)
if utils.Md5(req.Pwd) != res.Pwd {
resp.Status = common.RESP_ERROR
resp.Msg = "auth error"
return nil
}
if res.RoleId <= 0 {
res.RoleId = common.DefaultRoleId
}
resp.Status = common.RESP_SUCCESS
resp.Token, _ = utils.GetToken(res.UserId, res.RoleId, 600)
```
`grpc_server/utils/jwt.go`中jwt自定义字段新增角色id**RoleId**,以及jwt其它几个Api函数的适配。并同步修改到`grpc_gateway/utils/jwt.go`
```go
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
go-micro的学习资料 (470个子文件)
pb.bat 57B
pb.bat 57B
pb.bat 57B
pb.bat 57B
pb.bat 57B
pb.bat 57B
pb.bat 57B
pb.bat 57B
pb.bat 57B
pb.bat 57B
pb.bat 57B
pb.bat 57B
pb.bat 57B
pb.bat 57B
pb.bat 57B
pb.bat 57B
pb.bat 57B
pb.bat 57B
user.bat 46B
user.bat 46B
mail.bat 46B
user.bat 46B
mail.bat 46B
user.bat 46B
user.bat 46B
user.bat 46B
user.bat 46B
user.bat 46B
mail.bat 46B
gateway.bat 38B
gateway.bat 38B
gateway.bat 38B
gateway.bat 38B
gateway.bat 38B
gateway.bat 38B
gateway.bat 38B
rbac.bat 22B
rbac.bat 22B
rbac.bat 22B
rbac.bat 22B
client.bat 16B
client.bat 16B
client.bat 16B
client.bat 16B
client.bat 16B
client.bat 16B
client.bat 16B
client.bat 16B
service.conf 428B
service.conf 396B
service.conf 396B
service.conf 396B
service.conf 303B
service.conf 303B
service.conf 203B
service.conf 203B
service.conf 203B
service.conf 203B
service.conf 203B
service.conf 92B
service.conf 92B
service.conf 92B
service.conf 92B
process.conf 47B
service.conf 45B
service.conf 45B
service.conf 45B
process.conf 31B
process.conf 31B
process.conf 31B
process.conf 31B
process.conf 31B
process.conf 31B
process.conf 31B
process.conf 31B
user.pb.go 16KB
user.pb.go 16KB
user.pb.go 16KB
user.pb.go 16KB
user.pb.go 16KB
user.pb.go 16KB
user.pb.go 16KB
user.pb.go 16KB
user.pb.go 16KB
user.pb.go 16KB
user.pb.go 16KB
user.pb.go 16KB
eredis.go 11KB
eredis.go 11KB
eredis.go 11KB
eredis.go 11KB
user.pb.go 6KB
user.pb.go 6KB
mail.pb.go 6KB
user.pb.go 6KB
mail.pb.go 6KB
user.pb.go 6KB
user.pb.go 6KB
user.pb.go 6KB
user.pb.go 6KB
共 470 条
- 1
- 2
- 3
- 4
- 5
资源评论
毛小子
- 粉丝: 33
- 资源: 5
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功