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.

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

报告相同问题?

悬赏问题

  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!