基于go-micro微服务的实战-实现用户服务的注册和登录(四)

本文介绍如何使用Go微服务框架go-micro实现用户服务的注册与登录功能,包括编写proto文件、数据库表设计、业务逻辑处理及网关路由设置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基于go-micro微服务的实战-实现用户服务的注册和登录(四)

文章最后附带完整代码

基于go-micro实现用户服务实的注册和登录

工程目录上,每个往后的小节都是基于前一个小节的基础,环环相扣。所以这节就是基于第3节的工程目录扩展。

这节主要就是如何去实现用户的注册登录,依赖的第三方库的相关使用以及业务逻辑。

第三方库

  • gorm.io/gorm
  • github.com/astaxie/beego/validation
第一步:编写proto文件,新增grpc接口,编译生成

user.proto上继续新增接口和对应参数内容

service UserService{
    rpc UserReg(RegReq) returns(RegResp){}
    rpc UserLogin(LoginReq) returns(LoginResp){}
}

message RegReq{
    string name = 1;
    string phone =2;
    string email =3;
    string pwd = 4;
    string confir_pwd = 5;
}

message RegResp{
    int32 status = 1;
    string msg = 2;
}

message LoginReq{
    string phone =1;
    string pwd = 2;
}

message LoginResp{
    int32 status = 1;
    string user_id = 2;
    string msg = 3;
}


执行pb.bat或者pb.sh快速编译生成,grpc_gateway和grpc_user的proto都要同步添加和执行

第二步:新增user数据表和对应结构体定义

创建用户表,sql语句在user.sql

CREATE TABLE `user` (
  `user_id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户id',
  `name` varchar(50) NOT NULL COMMENT '名字',
  `phone` varchar(50) NOT NULL COMMENT '手机号',
  `pwd` varchar(50) NOT NULL COMMENT '密码',
  `reg_time` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '注册时间',
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=43 DEFAULT CHARSET=utf8 COMMENT='用户表';

user结构体定义,在models下新建user_model.go。其中的tag标识中,

  • gorm:"column:user_id;primaryKey",代表指定user_id为主键,并且User.Id对应的是user_id字段。
  • gorm:"-",代表写入db时候忽略该字段,gorm的语法规则
  • valid:"Required;MinSize(4);MaxSize(12)",valid标识的则是使用beego的validtion验证规则。
//用户
type User struct {
	Id int32 `gorm:"column:user_id;primaryKey"`
	Name string `valid:"Required;MinSize(4);MaxSize(12)"`
	Phone string `valid:"Mobile;Required"`
	Email string `valid:"Email;MaxSize(50)"`
	Pwd string `valid:"Required;MinSize(4);MaxSize(6)"`
	ConfirePwd string `gorm:"-" valid:"Required;MinSize(4);MaxSize(6)"`
	RegTime int64
}
第三步:用户服务的逻辑处理器实现新增的注册和登录接口

注册接口

func (u *UserHandler) UserReg(ctx context.Context, req *pb.RegReq, resp *pb.RegResp) error

请求数据的基础验证,使用github.com/astaxie/beego/validation验证非空,手机号,邮箱格式等等

	user := models.User{
		Name: req.Name,
		Phone: req.Phone,
		Email: req.Email,
		Pwd:req.Pwd,
		ConfirePwd:req.ConfirPwd,
		RegTime: time.Now().Unix(),
	}
	log.Printf("UserReg Params:%#v\n", user)

	//验证规则
	valid := validation.Validation{}
	b, err := valid.Valid(&user)
	if err !=nil{
		return err
	}
	if !b {
		for _, err := range valid.Errors {
			log.Println(err.Key, err.Message)
			resp.Status = common.RESP_ERROR
			resp.Msg = err.Message
			return nil
		}
	}

手机号和邮箱的唯一性判断

	//手机号是否未被注册
	var count int64
	models.Db.Table("user").Where("phone = ?", req.Phone).Count(&count)
	if count > 0 {
		resp.Status = 2
		resp.Msg = "phone is exists"
		return nil
	}

	//邮箱是否未被注册
	models.Db.Table("user").Where("email = ?", req.Email).Count(&count)
	if count > 0 {
		resp.Status = 2
		resp.Msg = "email is exists"
		return nil
	}

注册信息入库

	//写进数据库
	user.Pwd = utils.Md5(user.Pwd)

	result := models.Db.Create(&user)
	if result.Error != nil{
		return result.Error
	}

响应信息

	resp.Status = common.RESP_SUCCESS
	resp.Msg = "success"

登录接口

func (u *UserHandler) UserLogin(ctx context.Context, req *pb.LoginReq, resp *pb.LoginResp) error

请求数据的基础验证,使用github.com/astaxie/beego/validation验证手机号和密码的正确性

	valid := validation.Validation{}
	valid.Required(req.Phone, "phone")
	valid.Phone(req.Phone, "phone")
	valid.Required(req.Pwd, "pwd")
	valid.MinSize(req.Pwd, 4, "pwd")
	valid.MaxSize(req.Pwd, 6, "pwd")
	if valid.HasErrors() {
		for _, err := range valid.Errors {
			log.Println(err.Key, err.Message)
			resp.Status = common.RESP_ERROR
			resp.Msg = err.Message
			return nil
		}
	}

通过手机号和数据库的密码校验

	//获取数据库信息
	type result struct {
		UserId int32
		Pwd string
	}

	var res result
	models.Db.Table("user").Select("user.user_id, user.pwd").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
	}

响应信息,返回用户id

	resp.Status = common.RESP_SUCCESS
	resp.UserId = res.UserId
	resp.Msg = "success"
第四步:注册网关Gateway的路由

/grpc_gateway/router/router.go新增注册和登录路由。具体路由基础规则可看第3节

	//注册路由
	router.POST("/user/reg", handler.RoleReg)

	//登录路由
	router.POST("/user/login", handler.RoleLogin)
第五步:网关层注册和登录Http Api的请求处理

/grpc_gateway/handler/user_handler.go新增注册和登录处理

注册接口

func RoleReg(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	//解析参数
	var request map[string]interface{}
	if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
		log.Println("RoleReq ParseForm err:", err)
		http.Error(w, err.Error(), 500)
		return
	}

	log.Println(request)
	service := pb.NewUserService("emicro.user", common.Service.Client())
	resp, err := service.UserReg(context.Background(), &pb.RoleReg{
		Name: utils.GetString(request["name"]),
		Phone:utils.GetString(request["phone"]),
		Email: utils.GetString(request["email"]),
		Pwd: utils.GetString(request["pwd"]),
		ConfirPwd: utils.GetString(request["confire_pwd"]),
	})
	if err !=nil{
		log.Println("RoleReq err:", err)
		http.Error(w, err.Error(), 500)
		return
	}
	log.Println(resp.Status, resp.Msg)
	res := fmt.Sprintf("status:%d,msg:%v", resp.Status, resp.Msg)
	w.Write([]byte(res))
}

登录接口

func RoleLogin(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	//解析参数
	var request map[string]interface{}
	if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
		log.Println("RoleLogin ParseForm err:", err)
		http.Error(w, err.Error(), 500)
		return
	}

	log.Println(request)
	service := pb.NewUserService("emicro.user", common.Service.Client())
	resp, err := service.UserLogin(context.Background(), &pb.LoginReq{
		Phone:utils.GetString(request["phone"]),
		Pwd: utils.GetString(request["pwd"]),
	})
	if err !=nil{
		log.Println("RoleLogin err:", err)
		http.Error(w, err.Error(), 500)
		return
	}
	log.Println(resp.Status, resp.UserId, resp.Msg)
	res := fmt.Sprintf("status:%d,user_id:%d,msg:%v", resp.Status, resp.UserId, resp.Msg)
	w.Write([]byte(res))
}
第六步:启动网关服务和用户服务,采用Apipost测试

启动服务基于前面几节细讲,执行gateway.bat或者gateway.sh启动网关服务,执行user.bat或者user.sh启动用户服务


Apipost请求效果如图:

注册成功效果:reg
注册失败效果,邮件格式不正确:
reg_err
登录成功效果:
login
登录失败效果,密码不正确:
login_err

gitee完整代码链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值