go-zero jwt认证
编写login.api文件
// 声明语法版本,固定值
syntax = "v1"
type (
// 定义接口的请求体
loginReq {
username string `json:"username"`
password string `json:"password"`
}
// 定义接口的响应体
loginResp {
token string `json:"token"`
}
)
//不需要token的接口
service login-api {
@handler login
post /login (loginReq) returns (loginResp)
}
//需要token的接口
@server (
jwt: Auth
)
service login-api {
@handler cstest
get /cstest
}
通过在接口上添加
@server (
jwt: Auth
)
为接口开启jwt认证
生成代码
goctl api go -api login.api -dir .
修改配置
自动生成
package config
import "github.com/zeromicro/go-zero/rest"
type Config struct {
rest.RestConf
Auth struct {
AccessSecret string
AccessExpire int64
}
}
删除 AccessExpire int64,过期时间在生成token时设置
package config
import "github.com/zeromicro/go-zero/rest"
type Config struct {
rest.RestConf
Auth struct {
AccessSecret string
}
}
login-api.yaml添加AccessSecret
Name: login-api
Host: 0.0.0.0
Port: 8888
Auth:
AccessSecret: "XyesjsjjsksuM"
登录接口获取token
api\internal\logic\loginlogic.go
package logic
import (
"context"
"time"
"rpcjwt/api/internal/svc"
"rpcjwt/api/internal/types"
"github.com/golang-jwt/jwt/v4"
"github.com/zeromicro/go-zero/core/logx"
)
type LoginLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *LoginLogic {
return &LoginLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
// 登录获取token
func (l *LoginLogic) Login(req *types.LoginReq) (resp *types.LoginResp, err error) {
// todo: add your logic here and delete this line
mySigningKey := []byte("XyesjsjjsksuM")
type MyCustomClaims struct {
Userid string `json:"userid"`
jwt.RegisteredClaims
}
userid := "144551222554"
claims := MyCustomClaims{
userid,
jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)),
Issuer: "alsark",
},
}
tokeny := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
token, _ := tokeny.SignedString(mySigningKey)
return &types.LoginResp{
Token: token,
}, nil
}
这里 mySigningKey与 login-api.yaml中AccessSecret保持一致,是jwt签名秘钥
userid是模拟用户userid,可以在MyCustomClaims添加想携带的信息
ExpiresAt 为token有效期
jwt验证失败回调
api\login.go
package main
import (
"flag"
"fmt"
"net/http"
"zero/wfw1/api/internal/config"
"zero/wfw1/api/internal/handler"
"zero/wfw1/api/internal/svc"
"github.com/zeromicro/go-zero/core/conf"
"github.com/zeromicro/go-zero/rest"
"github.com/zeromicro/go-zero/rest/httpx"
)
var configFile = flag.String("f", "etc/shorturl-api.yaml", "the config file")
func main() {
flag.Parse()
var c config.Config
conf.MustLoad(*configFile, &c)
server := rest.MustNewServer(c.RestConf, rest.WithUnauthorizedCallback(JwtUnauthorizedResult))
defer server.Stop()
ctx := svc.NewServiceContext(c)
handler.RegisterHandlers(server, ctx)
fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
server.Start()
}
// JwtUnauthorizedResult jwt验证失败的回调
func JwtUnauthorizedResult(w http.ResponseWriter, r *http.Request, err error) {
httpx.WriteJson(w, http.StatusUnauthorized, "鉴权失败")
}
rest.MustNewServer添加 rest.WithUnauthorizedCallback(JwtUnauthorizedResult)
获取token里携带的信息
value := l.ctx.Value("userid")
需要token的接口
api\internal\logic\cstestlogic.go
package logic
import (
"context"
"fmt"
"rpcjwt/api/internal/svc"
"github.com/zeromicro/go-zero/core/logx"
)
type CstestLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewCstestLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CstestLogic {
return &CstestLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *CstestLogic) Cstest() error {
// todo: add your logic here and delete this line
value := l.ctx.Value("userid")
fmt.Println("打印userid", value)
return nil
}
完整代码示例
go-zero jwt认证: go-zero jwt认证https://gitee.com/alsark/go-zero-jwt-certification.git
Nginx路由配置
go-zero是微服务,那么实际项目部署的时候会有很多服务,不同服务不同接口,甚至不同服务在不同的服务器。那么这时候就需要有路由来给项目配置统一的域名。
其实就是利用Nginx的反向代理,来代理每个项目
这里我就用宝塔来设置
现在可以用 http://www.test.com/login 来访问 服务器8081服务上的login接口了