dph23577 2019-03-14 10:00
浏览 42
已采纳

net / http auth方法不稳定

I made my own auth (and single session auth) method that save session to redis, the method is :

  1. i check, is browser has cookie from my server, if is not, then create and save in browser
  2. check is the cookie id exist on redis if yes, next step if not redirect to login
  3. check what redis value by cookie id as key, the value will be username, if username exist, check what get value in redis by username, if username has cookie id value, then compare, is the cookie id same with current browser id, if it's not, redirect to login

Code

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

login :

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

the problem is, this auth method was unstable, idk why but after user succesfully login :

  1. access /blog redirect to login
  2. access /blog (with developer tool opened) working
  3. access /settings working
  4. after few minute / hours access /settings redirect to /login
  5. i do login, success, access /settings, redirected to /login again

yeah just unstable

note :

  1. i use "github.com/julienschmidt/httprouter" for routing
  2. "github.com/go-redis/redis" for redis
  • 写回答

1条回答 默认 最新

  • doufeng1249 2019-03-14 10:34
    关注

    The 301 response status means Moved Permanently, allowing browsers to cache the response indefinitely. Use 302 Found instead for the redirect, or don't redirect at all (you can just serve the login page immediately).

    Opening the developer tools most likely disabled caching, making it work.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 MS中不知道高分子的构型怎么构建模型
  • ¥60 QQOP数据,什么是op数据号,怎么提取op数据!能不能大量提取(语言-c语言)
  • ¥15 matlab代码 关于微分方程和嵌套的分段函数。
  • ¥15 onlyoffice编辑完后立即下载,下载的不是最新编辑的文档
  • ¥15 求caverdock使用教程
  • ¥15 Coze智能助手搭建过程中的问题请教
  • ¥15 12864只亮屏 不显示汉字
  • ¥20 三极管1000倍放大电路
  • ¥15 vscode报错如何解决
  • ¥15 前端vue CryptoJS Aes CBC加密后端java解密