我仍然是网络服务器的新手,随时随地学习(原谅双关语)。但有点困惑的是如何在不要求用户名和密码的情况下维护用户发出HTTP请求的身份。
我的客户端实际上是在C#(它是一个电脑游戏),我的服务器将收到来自应用程序的http请求。我可以在登录后发送用户ID,但是任何人都可以发送用户ID并伪装成一个他们不是这样的人,这不是一个安全问题吗?
我并不特别希望一直发送用户/通行证,因为这会因敏感信息而一直强制我使用HTTPS。
这是什么一般解决方案?我认为自从C#应用程序以来不能完成cookie,而不是像Chrome等浏览器。
答案 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)
您不需要每次客户端执行每次请求时都传递用户名和密码。有很多方法可以做到。
您可以使用cookie来这样做。为此,只要在服务器中成功登录,就可以制作cookie,并将其传递给客户端。数据将与客户端一起保存,然后您的服务器将读取cookie。
但是在您的情况下,不能像在C#中使用客户端那样使用cookie。因此,您需要使用下面列出的其他方式
您可以使用会话身份验证管理。会话是使任何登录安全可靠的最佳方法。为此,您必须生成一个会话密钥,然后将其用于验证已验证的用户。这将与每当客户端登录然后将生成一个新会话一样起作用,这样您就可以阻止创建的其他会话。
下面是代码,您可以参考:
登录功能
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)
}
}
创建会话
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)
}
删除会话
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