我正试着用大猩猩网络插座来启动图表. 身份验证中间件通过带有JWT令牌的Cookie工作. 我所有的端点都通过HTTP工作,但WebSocket不行. 在阅读了很多像Gorilla websocket with cookie authentication这样的话题后,我发现我的cookie是空的,我在WebSocket连接中的上下文也是空的.我不明白为什么?有人能给我解释一下为什么吗? 附注:我已经try 从该处理程序中删除Upgrader,Cookie和上下文传递得很好,但在升级到WebSocket协议后失败. 以下是我的文件: 终端:
func (r *router) routes(engine *gin.Engine) {
engine.Use(r.handler.VerifyUser())
engine.POST("/signup", r.handler.CreateUser)
engine.POST("/signin", r.handler.LoginUser)
engine.GET("/welcome", r.handler.Welcome)
engine.GET("/logout", r.handler.Logout)
engine.POST("/ws/createRoom", r.wsHandler.CreateRoom)
engine.GET("/ws/joinRoom/:roomId", r.wsHandler.JoinRoom)
}
WS_HANDER
func (h *Handler) JoinRoom(c *gin.Context) {
claims := c.Request.Context().Value("jwt").(models.Claims) //couldn't find value with "jwt" key
fmt.Println(claims.ID, claims.Name)
cookie, err := c.Cookie("chartJWT") // allways err no cookie
if err != nil {
fmt.Printf("no cookie, error:%v\n", err)
}
fmt.Printf("cookie: %+v\n", cookie)
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
中间件:
func (h *handler) VerifyUser() gin.HandlerFunc {
return func(c *gin.Context) {
notAuth := []string{"/signup", "/signin"}
requestPath := c.Request.URL.Path
for _, val := range notAuth {
if val == requestPath {
c.Next()
return
}
}
token, err := c.Cookie("chartJWT")
if err != nil {
c.Redirect(http.StatusPermanentRedirect, signinPage)
}
claims, ok := validateToken(token)
if !ok {
c.JSON(http.StatusBadRequest, gin.H{"error": errors.New("invalid token")})
return
}
c.Request = c.Request.WithContext(context.WithValue(c.Request.Context(), "jwt", *claims))
c.Next()
}
}
所有其他端点都可以工作,如果您需要任何其他代码,请让我知道.我不想把我的问题弄得更复杂,因为我认为它很简单,但我误解了一些事情( 感谢您的帮助和建议.
附言:如果我关闭中间件,一切都会正常工作.
最新情况: 添加了验证和生成函数
func validateToken(jwtToken string) (*models.Claims, bool) {
claims := &models.Claims{}
token, err := jwt.ParseWithClaims(jwtToken, claims, func(token *jwt.Token) (interface{}, error) {
return []byte(config.SECRETKEY), nil
})
if err != nil {
return claims, false
}
if !token.Valid {
return claims, false
}
return claims, true
}
func (h *handler) generateTokenStringForUser(id, name string) (string, error) {
// Create the JWT claims, which includes the username and expiry time
claims := models.Claims{
ID: id,
Name: name,
RegisteredClaims: jwt.RegisteredClaims{
Issuer: id,
ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)),
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err := token.SignedString([]byte(config.SECRETKEY))
return tokenString, err
}
添加了登录函数,其中添加了带有JWT字符串的Cookie
func (h *handler) LoginUser(c *gin.Context) {
var input models.LoginUserReq
if err := c.ShouldBindJSON(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
res, err := h.Service.LoginUser(context.Background(), &input)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
token, err := h.generateTokenStringForUser(res.ID, res.Name)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.SetCookie("chartJWT", token, 60*60*24, "/", "localhost", false, true)
c.JSON(http.StatusOK, gin.H{"user": res})
}
帮助后更新: 问题出在我的postman 设置请求中,我没有正确指定Cookie.