Я создаю небольшое приложение для управления ужином / планом (с использованием микросервисов) для пары знакомых. Предполагается, что каждый человек может войти в свою учетную запись, а затем пройти аутентификацию в других службах, используя токен-носитель (JWT).
Этот токен на предъявителя хранится в файле cookie. Однако я не могу найти этот файл cookie после того, как он был установлен, и я пытаюсь восстановить его снова.
Что в итоге приводит к ошибке
http: named cookie not present
Почему тело ответа на запрос пустое?
Почему по моему запросу GET не отправляются файлы cookie?
Как я могу исправить это?
Я немного обыскал сеть и попробовал следующее
Net / http cookie :
Реализация, которая кажется самой простой, а также та, которую я показываю здесь. Кажется, что этот тривиальный пример должен работать.
Реализация Cookiejar :
Я попытался использовать реализацию cookiejar для установки и получения файлов cookie как из браузера, так и из почтового отделения, однако это привело к тому же результату. Используемая мной реализация cookiejar описана в https://golang.org/pkg/net/http/cookiejar/?m=all#New
Установка на определенный URL и дополнительный запрос GET :
Я пытался разместить файлы cookie по другому определенному URL в моем домене. В какой-то момент казалось, что файлы cookie могут быть получены только с определенного определенного абсолютного URL, но это не так.
httputil DumpRequestOut :
Я обнаружил, что пакет утилит net / http имеет функцию DumpRequestOut, эта функция могла бы быть в состоянии извлечь тело из запроса, но это тоже было пусто.
Установка флага безопасности «cookie» в false :
Я обнаружил предположение, что флаг безопасности делает файлы cookie недоступными для чтения. К сожалению, изменение флага безопасности не дало никаких результатов.
Почтальон ясно показывает, что куки существуют. Мой браузер (firefox) также показывает, что куки существуют, но им было дано довольно абстрактное имя.
Запросы почтальона можно найти на https://www.getpostman.com/collections/fccea5d5dc22e7107664
Если я попытаюсь получить файлы cookie с помощью пакета «net / http» из golang, тело ответа будет пустым.
Я устанавливаю токены сеанса и перенаправляю клиента сразу после того, как аутентифицировал комбинацию пользователь / пароль.
// SetTokenAndRedirect sets an access token to the cookies
func SetTokenAndRedirect(w http.ResponseWriter, r *http.Request, db *mgo.Session, u *user.User, redirectURL string) *handler.AppError {
// Generate a unique ID for the session token.
tokenID := uuid.Must(uuid.NewV4()).String()
//set the expiration time (found in config.config.go)
expirationTime := time.Now().Add(config.ExpireTime)
// Set the cookie with the JWT
http.SetCookie(w, &http.Cookie{
Name: config.AccessTokenName,
Value: createToken(u.UserID, expirationTime, tokenID, r.Header.Get("User-Agent")),
Expires: expirationTime,
HttpOnly: true,
Secure: false,
})
// Redirects user to provided redirect URL
if redirectURL == "" {
return handler.AppErrorf(417, nil, "No redirect URL has been provided")
}
http.Redirect(w, r, redirectURL, 200)
return nil
}
Я пытаюсь проверить входящий запрос и токен JWT следующим образом.
// All handlers will have this adapted serveHTTP function
func (fn AppHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if err := Authorize(w, r); err != nil {
http.Error(w, fmt.Sprintf("Not Authorized: %v", err), http.StatusUnauthorized)
return
}
if e := fn(w, r); e != nil { // e is *appError, not os.Error.
log.Printf("Handler error: status code: %d, message: %s, underlying err: %#v",
e.Code, e.Message, e.Error)
http.Error(w, e.Message, e.Code)
}
}
// Claims defines what will be stored in a JWT access token
type Claims struct {
ProgramVersion string `json:"programVersion"`
UserAgent string `json:"userAgent"`
jwt.StandardClaims
}
// Authorize checks if the jwt token is valid
func Authorize(w http.ResponseWriter, r *http.Request) error {
c, err := r.Cookie("access_token")
if err != nil {
if err == http.ErrNoCookie {
// The program returns this error
return err
}
return err
}
tokenString := c.Value
claim := &Claims{}
tkn, err := jwt.ParseWithClaims(tokenString, claim, func(tkn *jwt.Token) (interface{}, error) {
return config.JwtSigningSecret, nil
})
if !tkn.Valid {
return err
}
if err != nil {
if err == jwt.ErrSignatureInvalid {
return err
}
return err
}
// JWT token is valid
return nil
}
Запрос структурирован следующим образом, когда устанавливает cookie
// Pretty printed version
Host: localhost:8080
content-type: application/json
user-agent: PostmanRuntime/7.11.0
cache-control: no-cache
accept-encoding: gzip, deflate
content-length: 68
connection: keep-alive
accept: */*
postman-token: 36268859-a342-4630-9fb4-c286f76d868b
cookie: access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwcm9ncmFtVmVyc2lvbiI6IjEuMC4wIiwidXNlckFnZW50IjoiUG9zdG1hblJ1bnRpbWUvNy4xMS4wIiwiZXhwIjoxNTU2MjA0MTg3LCJqdGkiOiJlZDlmMThhZi01NTAwLTQ0YTEtYmRkZi02M2E4YWVhM2M0ZDEiLCJpYXQiOjE1NTYyMDM1ODcsImlzcyI6ImdrLmp3dC5wcm9maWxlU2VydmljZS5hIn0.bssnjTZ8woKwIncdz_EOwYbCtt9t6V-7PmLxfq7GVyo
// Raw Version
&{POST /auth/users/login?redirect=/ HTTP/1.1 1 1 map[Cache-Control:[no-cache] Postman-Token:[d33a093e-c7ab-4eba-8c1e-914e85a0d289] Cookie:[access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwcm9ncmFtVmVyc2lvbiI6IjEuMC4wIiwidXNlckFnZW50IjoiUG9zdG1hblJ1bnRpbWUvNy4xMS4wIiwiZXhwIjoxNTU2MjA0NDU4LCJqdGkiOiIzOTk1MmI1NS0yOWQzLTQ4NGQtODhhNC1iMDlhYmI1OWEyNzgiLCJpYXQiOjE1NTYyMDM4NTgsImlzcyI6ImdrLmp3dC5wcm9maWxlU2VydmljZS5hIn0.DFA7KBET3C2q1A9N1hXGMT0QbabHgaVcDBpAYpBdbi8] Accept-Encoding:[gzip, deflate] Connection:[keep-alive] Content-Type:[application/json] User-Agent:[PostmanRuntime/7.11.0] Accept:[*/*] Content-Length:[68]] 0xc0001ba140 <nil> 68 [] false localhost:8080 map[redirect:[/]] map[] <nil> map[] [::1]:36584 /auth/users/login?redirect=/ <nil> <nil> <nil> 0xc00016a2a0}
Запрос структурирован следующим образом, когда получает cookie
// Pretty printed version
Host: localhost:8080
cache-control: no-cache
postman-token: 20f7584f-b59d-46d8-b50f-7040d9d40062
accept-encoding: gzip, deflate
connection: keep-alive
user-agent: PostmanRuntime/7.11.0
accept: */*
// Raw version
2019/04/25 12:22:56 &{GET /path/provide HTTP/1.1 1 1 map[User-Agent:[PostmanRuntime/7.11.0] Accept:[*/*] Cache-Control:[no-cache] Postman-Token:[b79a73a3-3e08-48a4-b350-6bde4ac38d23] Accept-Encoding:[gzip, deflate] Connection:[keep-alive]] {} <nil> 0 [] false localhost:8080 map[] map[] <nil> map[] [::1]:35884 /path/provide <nil> <nil> <nil> 0xc000138240}
Реакция строится следующим образом, когда устанавливает кук
response Headers: map[Location:[/] Set-Cookie:[access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwcm9ncmFtVmVyc2lvbiI6IjEuMC4wIiwidXNlckFnZW50IjoiR28taHR0cC1jbGllbnQvMS4xIiwiZXhwIjoxNTU2MjI4ODIyLCJqdGkiOiJlY2Q2NWRkZi1jZjViLTQ4N2YtYTNkYy00NmM3N2IyMmUzMWUiLCJpYXQiOjE1NTYyMjgyMjIsImlzcyI6ImdrLmp3dC5wcm9maWxlU2VydmljZS5hIn0.0sOvEzQS2gczjWSmtVSD_u0qMV2L7M4hKF1KUM08-bQ; Expires=Thu, 25 Apr 2019 21:47:02 GMT; HttpOnly] Date:[Thu, 25 Apr 2019 21:37:02 GMT] Content-Length:[0]]
Я ожидаю, что функция Authorize вернет ноль. Кроме того, если я добавлю следующий фрагмент кода, я ожидаю, что в нем присутствуют некоторые файлы cookie.
for _, cookie := range r.Cookies() {
fmt.Fprint(w, cookie.Name)
}
Однако функция Authorize возвращает ошибку в заголовке, и printf не распечатывает файлы cookie.