Я создал свой собственный метод аутентификации (и аутентификации в одном сеансе), который сохраняет сеанс в Redis, метод:
- Я проверяю, есть ли в браузере файл cookie с моего сервера, если нет, тосоздать и сохранить в браузере
- проверить, существует ли идентификатор куки на redis, если да, следующий шаг, если не перенаправить на логин
- проверить, какое значение redis по идентификатору куки в качестве ключа, значение будет именем пользователя, если имя пользователя существует, проверьте значение get в redis по имени пользователя, если имя пользователя имеет значение идентификатора cookie, а затем сравните, совпадает ли идентификатор cookie с текущим идентификатором браузера, если нет, перенаправьте на логин
Код
before_request:
func (hs BeforeRequest) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if !strings.Contains(r.RequestURI, "/login") && !strings.Contains(r.RequestURI, "/logout") {
// Check is user has `guid` cookie
Guid, err := r.Cookie("guid")
// if cookie not available, set cookie and redirect to login
if err != nil {
// Set the cookie
expiration := time.Now().Add(365 * 24 * time.Hour)
cookie := http.Cookie{Name: "guid", Value: helper.GenerateGuid(), Expires:expiration}
http.SetCookie(w, &cookie)
// Redirect to login
http.Redirect(w, r, "/login", 301)
return
} else {
// Return username that used by user (by it's Guid)
_, err := redisdb.Get(Guid.Value).Result()
if err != redis.Nil {
// Get active Guid by username, return active Guid
UsedFor, err := redisdb.Get(IsHasRedis).Result()
if err != redis.Nil && err == nil {
if UsedFor != Guid.Value {
fmt.Println("this account used in another session")
http.Redirect(w, r, "/login", 301)
return
}
} else {
// definitely not logged in
http.Redirect(w, r, "/login", 301)
return
}
} else {
// definitely not logged in
http.Redirect(w, r, "/login", 301)
return
}
}
}
// handle the request.
hs[0].ServeHTTP(w, r)
}
логин:
func LoginExecute(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
err := r.ParseForm() // Must be called before writing response
if err != nil {
fmt.Println(err)
} else {
if processRequest(r) {
Username, Password := r.Form["username"], r.Form["password"]
if len(Username) > 0 && len(Password) > 0 {
if len(Username[0]) <= 20 && len(Password[0]) <= 50 {
User := structs.Users{}
database, err := helper.DataDatabase()
if err != nil {
http.Error(w, "Couldn't Connect to Database", 500)
return
}
err = database.C("users").Find(bson.M{"username": Username[0]}).One(&User)
if err == nil {
CompareError := bcrypt.CompareHashAndPassword([]byte(User.Password), []byte(Password[0]))
if CompareError == nil {
Guid, err := r.Cookie("guid")
if err == nil {
redisdb.Set(Guid.Value, Username[0], 6 * time.Hour)
redisdb.Set(Username[0], Guid.Value, 6 * time.Hour)
http.Redirect(w, r, "/", 301)
} else {
http.Redirect(w, r, "/login?err=disabled-cookie", 301)
}
} else {
http.Redirect(w, r, "/login?err=password", 301)
}
} else {
http.Redirect(w, r, "/login?err=username", 301)
}
}
}
} else {
// recaptcha failed
http.Redirect(w, r, "/login?err=username", 301)
}
}
}
проблема в том, что этот метод аутентификации был нестабильным, IDK почему, но после того, как пользователь успешно логинится:
- доступ / перенаправление блога для входа в систему
- доступ / блог (с открытым инструментом разработчика) работает
- доступ / настройки работают
- через несколько минут / часов доступа/ настройки перенаправить на / логин
- я делаю вход, успех, доступ / настройки, перенаправлен на / вход снова
да просто нестабильно
примечание:
- я использую "github.com / julienschmidt / httprouter "для маршрутизации
- " github.com/go-redis/redis "для redis