func Login(c echo.Context) error {
user := &users.User{}
if err := c.Bind(&user); err != nil {
return err
}
return token.SigIn(c, user.Email, user.Password)
}
这是我的登录功能,在用户发送请求时检索令牌。
处理令牌的登录功能
func SigIn(c echo.Context, email, password string) error {
user := users.User{}
db := database.SetUp()
if err := db.Where("email = ?", email).First(&user).Error; gorm.IsRecordNotFoundError(err) {
restErr := errors.NewBadRequestError("Invalid credentials")
return c.JSON(http.StatusBadRequest, restErr)
}
if user.VerifyPassword(password) != nil {
restErr := errors.NewUnauthorizedError("Couldn't log you in with these credentials")
return c.JSON(http.StatusUnauthorized, restErr)
}
//user is successfull
return CreateToken(c)
}
CreateToken函数如下
type TokenJWT struct {
Token string `json:"token"`
}
func CreateToken(c echo.Context) error {
token := jwt.New(jwt.SigningMethodHS256)
claims := token.Claims.(jwt.MapClaims)
claims["authorized"] = true
claims["name"] = "Pascal Gaetan"
claims["exp"] = time.Now().Add(time.Hour * 1).Unix()
// Generate encoded token and send it as response.
t, err := token.SignedString([]byte("my_secret_key"))
if err != nil {
return err
}
return c.JSON(http.StatusOK, TokenJWT{
Token: t,
})
}
当一切成功时,我想通过调用Me函数的URL / api / me获取经过身份验证的用户
答案 0 :(得分:1)
让我将您的问题分为两个部分:第一部分是如何轻松地在JWT令牌中或从JWT令牌中编码和解码用户,第二部分是如何编写可从任何地方检索用户的通用代码。
在您的示例中,我提到您创建了MapClaims,但是为了降低解析的复杂性,最好使用自定义声明类型创建令牌。如果您使用的是dgrijalva / jwt-go,则根据文档,您可以执行类似的操作
type UserClaims struct {
Name string `json:"name"`
jwt.StandardClaims
}
// encode it as before, but with your created type
t := jwt.New(signer)
userClaims := &UserClaims{Name: "Burmese"}
t.Claims = userClaims
tokenString, err = t.SignedString(]byte("my_secret_key"))
然后您可以使用
在路由器/框架中间件中解析用户tokenString := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJleHAiOjE1MDAwLCJpc3MiOiJ0ZXN0In0.HE7fK0xOQwFEr4WDgRWj4teRPZ6i3GLwD5YCm6Pwu_c"
token, err := jwt.ParseWithClaims(tokenString, &UserClaims{}, func(token *jwt.Token) (interface{}, error) {
return []byte("my_secret_key"), nil
})
if claims, ok := token.Claims.(*UserClaims); ok && token.Valid {
fmt.Printf("%v %v", claims.Name, claims.StandardClaims.ExpiresAt)
} else {
fmt.Println(err)
}
此示例摘自官方文档here
现在,您知道如何轻松解析经过身份验证的用户结构,下一步的逻辑就是将其包装到中间件中。是否有很多实现细节,例如可以从cookie,标头或查询中检索JWT,还可以对它们定义一些顺序,请根据以下内容进行操作:您应该将上述代码包装到中间件中,并在解析结构后可以传递它通过您的请求上下文。我不使用echo和其他框架,但对于纯net / http,您可以使用
从中间件传递已解析的结构context.WithValue(ctx, UserCtxKey, claims)
希望有帮助!
答案 1 :(得分:0)
这是一种相当常见的设计模式,用于创建经过身份验证的客户端,然后在其上调用各种操作方法。您可以执行以下操作:
type Client struct {
... // other members
token string // unexported unless there is a special reason to do otherwise
}
func NewClient(c echo.Context, email, password string) (*Client, error) {
user := users.User{}
cl := Client{}
... // your original method
cl.token = token
return &cl, nil
}
func (c *Client) DoSomething(...) ... { ... }