【问题标题】:Golang - How can I get authorization from mux?Golang - 我如何从 mux 获得授权?
【发布时间】:2019-09-28 15:25:23
【问题描述】:

我是 Golang 的新手,我开始使用 JWT 学习 Gorilla/Mux。

我只是成功地将用户注册到 MongoDB,然后登录。 我使用 Postman 进行测试。但是当我尝试浏览受保护的路线时。 我在验证中收到错误“缺少身份验证令牌”。

邮递员如何获得授权浏览受保护的路由?

以下是注册登录代码:

路由器功能

func Router() *mux.Router {

    router := mux.NewRouter().StrictSlash(true)
  router.Use(CommonMiddleware)

  //router.HandleFunc("/", middleware.TestAPI).Methods("GET", "OPTIONS")
  router.HandleFunc("/register", middleware.RegisterHandler).Methods("POST", "OPTIONS")
  router.HandleFunc("/login", middleware.LoginHandler).Methods("POST", "OPTIONS")

  secure := router.PathPrefix("/auth").Subrouter()
  secure.Use(auth.JwtVerify)

    secure.HandleFunc("/api/task", middleware.GetAllTask).Methods("GET", "OPTIONS")
    secure.HandleFunc("/api/task", middleware.CreateTask).Methods("POST", "OPTIONS")
    secure.HandleFunc("/api/task/{id}", middleware.TaskComplete).Methods("PUT", "OPTIONS")
    secure.HandleFunc("/api/undoTask/{id}", middleware.UndoTask).Methods("PUT", "OPTIONS")
    secure.HandleFunc("/api/deleteTask/{id}", middleware.DeleteTask).Methods("DELETE", "OPTIONS")
    secure.HandleFunc("/api/deleteAllTask", middleware.DeleteAllTask).Methods("DELETE", "OPTIONS")
    return router
}

func CommonMiddleware(next http.Handler) http.Handler {
  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    w.Header().Add("Content-Type", "application/json")
    w.Header().Set("Access-Control-Allow-Origin", "*")
    w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
    w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, Access-Control-Request-Headers, Access-Control-Request-Method, Connection, Host, Origin, User-Agent, Referer, Cache-Control, X-header")
    next.ServeHTTP(w, r)
  })
}

注册函数

func RegisterHandler(w http.ResponseWriter, r *http.Request) {
  w.Header().Set("Content-Type", "application/json")
  var user models.User
  body, _ := ioutil.ReadAll(r.Body)
  err := json.Unmarshal(body, &user)
  var res models.ResponseResult
  if err != nil {
    res.Error = err.Error()
    json.NewEncoder(w).Encode(res)
    return
  }

  var result models.User
  err = usercollection.FindOne(context.TODO(), bson.D{{"username", user.Username}}).Decode(&result)

  if err != nil {
    if err.Error() == "mongo: no documents in result" {
      hash, err := bcrypt.GenerateFromPassword([]byte(user.Password), 5)

      if err != nil {
        res.Error = "Error While Hashing Password, Try Again"
        json.NewEncoder(w).Encode(res)
        return
      }
      user.Password = string(hash)

      _, err = usercollection.InsertOne(context.TODO(), user)
      if err != nil {
        res.Error = "Error While Creating User, Try Again"
        json.NewEncoder(w).Encode(res)
        return
      }
      res.Result = "Register Successful"
      json.NewEncoder(w).Encode(res)
      return
    }
    res.Error = err.Error()
    json.NewEncoder(w).Encode(res)
    return
  }
  res.Result = "Username already exists!!"
  json.NewEncoder(w).Encode(res)
  return
}

登录功能

func LoginHandler(w http.ResponseWriter, r *http.Request) {
  w.Header().Set("Content-Type", "application/json")
  var user models.User
  body, _ := ioutil.ReadAll(r.Body)
  err := json.Unmarshal(body, &user)

  if err != nil {
    log.Fatal(err)
  }
  //var resultToken models.Token
  var resultUser models.User
  var res models.ResponseResult

  err = usercollection.FindOne(context.TODO(), bson.D{{"username", user.Username}}).Decode(&resultUser)

  if err != nil {
    res.Error = "Invalid username"
    json.NewEncoder(w).Encode(res)
    return
  }

  expiresAt := time.Now().Add(time.Minute * 100000).Unix()

  errf := bcrypt.CompareHashAndPassword([]byte(resultUser.Password), []byte(user.Password))

  if errf != nil && errf == bcrypt.ErrMismatchedHashAndPassword {
    var  res = map[string]interface{}{"status": false, "message": "Invalid login credential. Please try again"}
    json.NewEncoder(w).Encode(res)
    return
  }
  tk := &models.Token{
    Username: user.Username,
    StandardClaims: &jwt.StandardClaims{
      ExpiresAt: expiresAt,
    },
  }

  token := jwt.NewWithClaims(jwt.GetSigningMethod("HS256"), tk)

  tokenString, err := token.SignedString([]byte("secret"))

  if err != nil {
    res.Error = "Error while generating token, Try again"
    json.NewEncoder(w).Encode(res)
    return
  }
  var resp = map[string]interface{}{"status": false, "message": "logged in"}
  resp["token"] = tokenString
  resp["tk"] = tk

  json.NewEncoder(w).Encode(resp)
}

验证函数

func JwtVerify(next http.Handler) http.Handler {
  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    var header = r.Header.Get("x-access-token")

    json.NewEncoder(w).Encode(r)
    header = strings.TrimSpace(header)

    if header == "" {
      w.WriteHeader(http.StatusForbidden)
      json.NewEncoder(w).Encode(Exception{Message: "Missing auth token"})
      return
    }

    tk := &models.Token{}

    _, err := jwt.ParseWithClaims(header, tk, func(token *jwt.Token) (interface{}, error) {
      return []byte("secret"), nil
    })

    if err != nil {
      w.WriteHeader(http.StatusForbidden)
      json.NewEncoder(w).Encode(Exception{Message: err.Error()})
      return
    }

    ctx := context.WithValue(r.Context(), "user", tk)
    next.ServeHTTP(w, r.WithContext(ctx))
  })
}

【问题讨论】:

    标签: go postman gorilla


    【解决方案1】:

    由于您在请求标头中检查令牌x-access-token,因此您需要在发送请求时添加相同的标记。这可以在 Postman 中轻松完成,如下所示 -

    我用的路由器是-

    主包

    func router() *mux.Router {
        router := mux.NewRouter().StrictSlash(true)
        secure := router.PathPrefix("/auth").Subrouter()
        secure.Use(auth.JwtVerify)
        secure.HandleFunc("/api", middleware.ApiHandler).Methods("GET")
        return router
    }
    
    func main() {
        r := router()
        http.ListenAndServe(":8080", r)
    }
    

    我用过的中间件是-

    包授权

    func JwtVerify(next http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            var header = r.Header.Get("x-access-token")
    
            json.NewEncoder(w).Encode(r)
            header = strings.TrimSpace(header)
    
            if header == "" {
                w.WriteHeader(http.StatusForbidden)
                json.NewEncoder(w).Encode("Missing auth token")
                return
            } else {
                json.NewEncoder(w).Encode(fmt.Sprintf("Token found. Value %s", header))
            }
            next.ServeHTTP(w, r)
        })
    }
    

    处理程序是 -

    打包中间件

    func ApiHandler(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusOK)
        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode("SUCCESS!")
        return
    }
    

    【讨论】:

      猜你喜欢
      • 2013-09-04
      • 2017-08-25
      • 2019-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      • 2022-09-27
      相关资源
      最近更新 更多