定义登录验证protobuf
修改proto/user/user.proto
syntax = "proto3";package micro.service.user;option go_package = "proto/user";service UserService {rpc Pagination(PaginationRequest) returns(PaginationResponse){}rpc Get(GetRequest) returns(UserResponse){}rpc Create(CreateRequest) returns(UserResponse){}rpc Update(UpdateRequest) returns(UserResponse){}rpc Delete(DeleteRequest) returns(UserResponse){}rpc Auth(AuthRequest) returns(TokenResponse){}rpc ValidateToken(TokenRequest) returns(TokenResponse){}}message User{uint64 id = 1;string name = 3;string email = 4;string real_name = 6;string avatar = 7;string create_at = 9;string update_at = 10;}//UserResponse 单个用户响应message UserResponse{User user = 1;}//PaginationResponse 用户分页数据响应message PaginationResponse{repeated User users = 1;uint64 total = 2;}//PaginationRequest 用户分页请求message PaginationRequest{uint64 page = 1;uint32 perPage = 2;}//GetRequest 获取单个用户请求message GetRequest{uint64 id = 1;}//CreateRequest 创建用户请求message CreateRequest{string name = 1;string password = 2;string email = 3;string real_name = 4;string avatar = 5;}//UpdateRequest 更新用户请求message UpdateRequest{uint64 id = 1;string name = 2;string email = 3;string real_name = 4;string avatar = 6;}//DeleteRequest 删除用户请求message DeleteRequest{uint64 id = 1;}//AuthRequest 登录请求message AuthRequest{string email = 1;string password = 2;}//TokenRequest token验证接口message TokenRequest{string token = 1;}//TokenResponse token响应接口message TokenResponse{string token = 1;bool valid = 2;}
生成protobuf代码
make proto
引用jwt编写获取token业务
获取jwt生成包
go get -u github.com/dgrijalva/jwt-go
创建service目录
mkdir servicetouch service/token.go
package serviceimport ("github.com/869413421/micro-service/user/pkg/model""github.com/869413421/micro-service/user/pkg/repo""github.com/dgrijalva/jwt-go""time")var (key = []byte("microServiceUserTokenKeySecret"))// CustomClaims jwt认证对象type CustomClaims struct {User *model.Userjwt.StandardClaims}// Authble jwt实现接口type Authble interface {Decode(token string) (*CustomClaims, error)Encode(user *model.User) (string, error)}// TokenService token业务对象type TokenService struct {Repo repo.UserRepositoryInterface}// NewTokenService token业务初始化func NewTokenService() Authble {return &TokenService{Repo: repo.NewUserRepository()}}// Decode 将token字符串转换为token对象func (srv *TokenService) Decode(tokenString string) (*CustomClaims, error) {// Parse the tokentoken, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {return key, nil})// Validate the token and return the custom claimsif claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {return claims, nil} else {return nil, err}}// Encode 将token对象串转换为token字符串func (srv *TokenService) Encode(user *model.User) (string, error) {expireToken := time.Now().Add(time.Hour * 72).Unix()// Create the Claimsclaims := CustomClaims{user,jwt.StandardClaims{ExpiresAt: expireToken,Issuer: "micro.service.user",},}// Create tokentoken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)// Sign token and returnreturn token.SignedString(key)}
实现服务处理器
为UserServiceHandler增加token业务层
...//UserServiceHandler 用户服务处理器type UserServiceHandler struct {UserRepo repo.UserRepositoryInterfaceTokenService service.Authble}// NewUserServiceHandler 用户服务初始化func NewUserServiceHandler() *UserServiceHandler {return &UserServiceHandler{UserRepo: repo.NewUserRepository(),TokenService: service.NewTokenService(),}}...
实现登录验证token接口
为UserServiceHandler加上实现方法
...// Auth 认证获取tokenfunc (srv UserServiceHandler) Auth(ctx context.Context, req *pb.AuthRequest, rsp *pb.TokenResponse) error {// 1.根据邮箱回去用户log.Println("Logging in with:", req.Email, req.Password)user, err := srv.UserRepo.GetByEmail(req.Email)if err != nil && err != gorm.ErrRecordNotFound {return err}if err == gorm.ErrRecordNotFound {return errors.NotFound("User.Auth.GetByEmail.Error", "user not found ,check you password or email")}// 2.检验用户密码err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password))if err != nil {return errors.Unauthorized("User.Auth.CheckPassword.Error", err.Error())}// 3.生成tokentoken, err := srv.TokenService.Encode(user)if err != nil {return err}// 4.返回token字符串rsp.Token = tokenreturn nil}// ValidateToken 验证tokenfunc (srv *UserServiceHandler) ValidateToken(ctx context.Context, req *pb.TokenRequest, rsp *pb.TokenResponse) error {// 1.将token字符串转换为token对象claims, err := srv.TokenService.Decode(req.Token)if err != nil {return err}// 2.判断转换是否成功if claims.User.ID == 0 {return errors.BadRequest("User.ValidateToken.Error", "user invalid")}// 3.返回验证状态rsp.Token = req.Tokenrsp.Valid = truereturn nil}...
编译代码准备测试
make build
