如何在Go服务器上识别用户而不经常传递用户名/密码

时间:2017-11-04 03:52:55

标签: go server

我仍然是网络服务器的新手,随时随地学习(原谅双关语)。但有点困惑的是如何在不要求用户名和密码的情况下维护用户发出HTTP请求的身份。

我的客户端实际上是在C#(它是一个电脑游戏),我的服务器将收到来自应用程序的http请求。我可以在登录后发送用户ID,但是任何人都可以发送用户ID并伪装成一个他们不是这样的人,这不是一个安全问题吗?

我并不特别希望一直发送用户/通行证,因为这会因敏感信息而一直强制我使用HTTPS。

这是什么一般解决方案?我认为自从C#应用程序以来不能完成cookie,而不是像Chrome等浏览器。

3 个答案:

答案 0 :(得分:3)

  

我认为自C#应用程序以来不能完成cookie,而不是Chrome等浏览器。

Cookie只是一个名为Cookie的标题,对于任何合理的HTTP库都不是问题。

  

我并不是特别想要一直发送用户/通行证,因为这会因敏感信息而一直迫使我使用HTTPS。

这就是Facebook,Twitter和其他大多数网站10年前所做的事情。安全登录页面可防止您的凭据被盗,但您点击的其他不安全端点会显示您用于进行身份验证的其他信息。这样,您的用户就可以被监控您不安全连接的任何人模仿。请参阅Firesheep

由于您应该安全地存储用户的密码,我会设想验证每个请求的用户密码是否缓慢。

如果一个帐户保证永远不会被多个客户端使用,您可以为每个用户生成一个随机API令牌,与其用户名和密码无关。否则,您必须在用户登录时生成随机会话令牌,并将其映射到具有某种数据库的实际用户。这就是大多数网站处理登录的方式。

无论您做什么,如果他们知道他们的秘密(用户名+密码或会话ID),就无法阻止他人冒充其他帐户。这就是您必须使用HTTPS而不仅仅是HTTP的原因。

答案 1 :(得分:1)

我认为典型的方法是使用会话ID:https://en.wikipedia.org/wiki/Session_ID

答案 2 :(得分:0)

您不需要每次客户端执行每次请求时都传递用户名和密码。有很多方法可以做到。

  1. 您可以使用cookie来这样做。为此,只要在服务器中成功登录,就可以制作cookie,并将其传递给客户端。数据将与客户端一起保存,然后您的服务器将读取cookie。

    但是在您的情况下,不能像在C#中使用客户端那样使用cookie。因此,您需要使用下面列出的其他方式

  2. 您可以使用会话身份验证管理。会话是使任何登录安全可靠的最佳方法。为此,您必须生成一个会话密钥,然后将其用于验证已验证的用户。这将与每当客户端登录然后将生成一个新会话一样起作用,这样您就可以阻止创建的其他会话。

下面是代码,您可以参考:

  1. 登录功能

    func login(w http.ResponseWriter, r *http.Request) {
        sess := globalSessions.SessionStart(w, r)
        r.ParseForm()
        if r.Method == "GET" {
            t, _ := template.ParseFiles("login.gtpl")
            w.Header().Set("Content-Type", "text/html")
            t.Execute(w, sess.Get("username"))
        } else {
            sess.Set("username", r.Form["username"])
            http.Redirect(w, r, "/", 302)
        }
    }
    
  2. 创建会话

    func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (session Session) {
        manager.lock.Lock()
        defer manager.lock.Unlock()
        cookie, err := r.Cookie(manager.cookieName)
        if err != nil || cookie.Value == "" {
            sid := manager.sessionId()
            session, _ = manager.provider.SessionInit(sid)
            cookie := http.Cookie{Name: manager.cookieName, Value: url.QueryEscape(sid), Path: "/", HttpOnly: true, MaxAge: int(manager.maxlifetime)}
            http.SetCookie(w, &cookie)
        } else {
            sid, _ := url.QueryUnescape(cookie.Value)
            session, _ = manager.provider.SessionRead(sid)
        }
        return
    }
    func (manager *Manager) sessionId() string {
        b := make([]byte, 32)
        if _, err := io.ReadFull(rand.Reader, b); err != nil {
            return ""
        }
        return base64.URLEncoding.EncodeToString(b)
    }
    
  3. 删除会话

    func init() {
        go globalSessions.GC()
    }
    
    func (manager *Manager) GC() {
        manager.lock.Lock()
        defer manager.lock.Unlock()
        manager.provider.SessionGC(manager.maxlifetime)
        time.AfterFunc(time.Duration(manager.maxlifetime), func() { manager.GC() })
    }
    

参考 https://astaxie.gitbooks.io/build-web-application-with-golang/en/06.2.html