将变量从中间件传递到结束函数

时间:2018-01-12 11:58:02

标签: go

我正在使用中间件(CheckToken)检查JWT并获取自定义声明(Id)(它将是我的数据库中用户的ID)但我需要将其传递给campaign.Attack(所以我可以知道谁是正在进行“攻击”的用户),但我无法找到办法。

我尝试将其作为next(w, req, claim.id) token.go中的参数传递给我,但我需要触及http.HandlerFunc函数,因此这不是一个有效选项。

关于如何将claim.idCheckToken传递到campaign.Attack()的任何想法?

谢谢

         ***** main.go*****

            func main() {

                router := mux.NewRouter()

                router.HandleFunc("/attack", token.CheckToken(campaign.Attack)).Methods("GET", "OPTIONS")

               log.Fatal(http.ListenAndServe(":3000", handlers.CORS(handlers.AllowedOrigins([]string{"*"}),
                    handlers.AllowedHeaders([]string{"Content-Type", "authorization"}))(router)))
            }



            ******campaign.go*****

            package campaign

            import (
                "log"
                "net/http"

            )


            func init() {

            }

            func Attack(w http.ResponseWriter, req *http.Request) {
                log.Println("attack")

                //i need to get the claim.Id here
            }


            ****token.go****

type MyCustomClaims struct {
    Id int `json:"id"`  //the Id of the user 
    jwt.StandardClaims
}

            func CheckToken(next http.HandlerFunc) (MyCustomClaims, http.HandlerFunc) {
                return MyCustomClaims{}, http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {

                    authorizationHeader := req.Header.Get("authorization")
                    if authorizationHeader != "" {
                        bearerToken := strings.Split(authorizationHeader, " ")
                        if len(bearerToken) == 2 {
                            token, err := jwt.ParseWithClaims(bearerToken[1], &MyCustomClaims{}, func(token *jwt.Token) (interface{}, error) {
                                return []byte("magicword"), nil
                            })

                            if token.Valid {


                                if claims, ok := token.Claims.(*MyCustomClaims); ok && token.Valid {
                               //**************************
                              //***********i have the claims.id here and it works.*******
                              //**************************
                                    log.Println(claims.Id)

                              //but i need to pass it or find a way to read it in campaign.Attack()
                                    next(w, req)
                                } else {
                                    log.Println(err)
                                }
                            } else if ve, ok := err.(*jwt.ValidationError); ok {
                                if ve.Errors&jwt.ValidationErrorMalformed != 0 {


                                } else if ve.Errors&(jwt.ValidationErrorExpired|jwt.ValidationErrorNotValidYet) != 0 {
                                    // Token is either expired or not active yet

                                } 
                            } 
                        } 
                    } 


                })

            }

2 个答案:

答案 0 :(得分:0)

使用上下文的方法WithValue。 而是下一步(w,req)写

   ctx := context.WithValue(r.Context(), "claim_id", claims.Id)
   next(w, req.WithContext(ctx))

和内部攻击:

   claim_id, ok := r.Context().Value("claim_id").(int)
   if !ok {
     return // I don't have context .. sorry
   }
   // use claim_id

我还没有提到,如何创建一个独特的密钥......但有时在未来。

答案 1 :(得分:0)

查看CheckToken ..它应该是中间件,典型的midleware传递http.Handler并且可能是另一个参数并返回另一个http.Handler(这比使用http.HandlerFunc好一点)。返回函数通常调用参数并在此调用之前或之后执行一些操作。

func CheckToken(next http.Handler) http.Handler
{
   return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
     // and body the same as you have in the answer, but instead of next(w, req) put there two lines "WithValue"
   }
}

进入攻击的开始,接下来几行,我已经给你了