如何在Golang中检索经过身份验证的用户

时间:2020-05-10 04:52:23

标签: go jwt-auth

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获取经过身份验证的用户

2 个答案:

答案 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(...) ... { ... }