net / http auth方法不稳定

时间:2019-03-14 10:00:33

标签: go cookies redis

我制作了自己的auth(和单会话auth)方法,用于将会话保存到redis,该方法是:

  1. 我检查一下,浏览器是否有来自我服务器的cookie,如果不是,则创建并保存在浏览器中
  2. 如果是,请检查redis上是否存在cookie id,如果不是,请下一步进行重定向
  3. 检查以cookie id作为键的redis值,该值将为username,如果存在username,则检查redis按username获取的值,如果username具有cookie id值,则进行比较,该cookie id与当前浏览器是否相同id,如果不是,则重定向到登录

代码

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

问题是,此auth方法不稳定,idk为什么但在用户成功登录后:

  1. 访问/ blog重定向至登录
  2. 访问/ blog(打开开发人员工具)正常工作
  3. 访问/设置正常
  4. 几分钟/小时后,访问/设置将重定向到/ login
  5. 我进行登录,成功,访问/设置,再次重定向到/ login

是的,只是不稳定

注意:

  1. 我使用“ github.com/julienschmidt/httprouter”进行路由
  2. “ github.com/go-redis/redis”(用于redis)

1 个答案:

答案 0 :(得分:2)

“ 301”响应状态表示“已永久移动”,允许浏览器无限期缓存响应。改用302 Found进行重定向,或者根本不重定向(您可以立即提供登录页面)。

打开开发人员工具很可能会禁用缓存,从而使其正常工作。