Golang - Как я могу получить разрешение от mux? - PullRequest
1 голос
/ 24 сентября 2019

Я новичок в Golang, я начинаю изучать Gorilla / Mux с помощью JWT.

Я просто успешно зарегистрировал пользователя в MongoDB и затем вошел в систему.Я использую Почтальон, чтобы проверить.Но когда я пытаюсь перейти к защищенному маршруту.Я получаю сообщение об ошибке «Отсутствует токен авторизации», как при проверке.

Как почтальон может получить разрешение на просмотр защищенного маршрута?

Ниже приведен код регистрации и логина:

Функция маршрутизатора

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))
  })
}

1 Ответ

1 голос
/ 26 сентября 2019

Поскольку вы проверяете токен x-access-token в заголовке запроса, вам необходимо добавить его при отправке запроса.Это можно легко сделать в Почтальоне, как показано ниже -

Screenshot of Postman showing how to set header in http request

Я использовал маршрутизатор -

основной пакет

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)
}

Промежуточное программное обеспечение, которое я использовал, -

auth пакета

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
}
...