在Cookie中传递多个值时卡住了。我无法找到更好的方法来管理会话和cookie。试图使用github.com/gorilla/securecookie
这个包。
package main
import (
"database/sql"
"log"
"net/http"
"shambhavi/packages/loginPkg"
_ "github.com/go-sql-driver/mysql"
"github.com/gorilla/mux"
)
var router = mux.NewRouter()
var db *sql.DB
func connectDb() *sql.DB {
db, dberr := sql.Open("mysql", "root:root@tcp(127.0.0.1:8889)/shambhavi_db")
if dberr != nil {
log.Println(dberr)
}
return db
}
func login(w http.ResponseWriter, r *http.Request) {
var db *sql.DB = connectDb()
loginPkg.LoginOperation(w, r, db)
}
func main() {
http.HandleFunc("/demo", login)
http.Handle("/", router)
err := http.ListenAndServe(port, nil) // setting listening port
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
package loginPkg
import (
"database/sql"
"encoding/json"
"fmt"
"net/http"
"shambhavi/packages/sessionPkg"
_ "github.com/go-sql-driver/mysql"
)
var retMap = make(map[string]string)
func ErrorHandler(err error) {
if err != nil {
panic(err)
}
}
func LoginOperation(w http.ResponseWriter, r *http.Request, db *sql.DB) {
fmt.Println("In LoginOperation ")
r.ParseForm()
if len(r.Form["username"][0]) == 0 && len(r.Form["password"][0]) == 0 {
fmt.Fprintf(w, "Something is blank !!!")
} else {
var lvl string
var uFullName string
err := db.QueryRow("SELECT lvl_flag FROM admin_instance WHERE user_name = ? AND passwd = ?", r.FormValue("username"), r.FormValue("password")).Scan(&lvl)
er := db.QueryRow("SELECT emp_name FROM emp_detail WHERE emp_uname = ?", r.FormValue("username")).Scan(&uFullName)
ErrorHandler(er)
retMap["msg"] = "Login successfully"
retMap["err"] = "Not Login"
retMap["lvl"] = lvl
retMap["fullName"] = uFullName
b, _ := json.Marshal(retMap)
if err != nil {
fmt.Println(err)
fmt.Fprintf(w, "%s", b)
} else {
if lvl == "1" || lvl == "2" || lvl == "3" {
sessionPkg.SetSession(w, r, r.FormValue("username"), retMap) // Passing map to the fun, retMap
fmt.Fprintf(w, "%s", b)
usrnm := sessionPkg.GetUserName(r)
fmt.Println("From session variable", usrnm)
} else {
fmt.Println("Chukala ....")
fmt.Fprintf(w, "%s", b)
}
}
}
defer db.Close()
}
问题在于以下文件......
package sessionPkg
import (
"fmt"
"net/http"
"time"
"github.com/gorilla/securecookie"
)
var cookieHandler = securecookie.New(
securecookie.GenerateRandomKey(64),
securecookie.GenerateRandomKey(32))
func SetSession(w http.ResponseWriter, r *http.Request, username string, retMap map[string]string) {
sessionData := map[string]string{
"userName": username,
"lvl": retMap["lvl"],
"fullName": retMap["fullName"],
}
expiration := time.Now().Add(365 * 24 * time.Hour)
//if encoded, err := cookieHandler.Encode("session", sessionData); err == nil {
cookie := http.Cookie{
Name: "session",
Value: sessionData["userName"], //Here i want map or something else that can accept multiple values
Expires: expiration,
//MaxAge: 3600,
}
http.SetCookie(w, &cookie)
//}
}
func GetUserName(request *http.Request) (userName string) {
//fmt.Println(request.Cookie("session"))
cookieValue := make(map[string]string)
if cookie, err := request.Cookie("session"); err == nil {
fmt.Println("cookieValue = ", cookie.Value)
//if err = cookieHandler.Decode("session", cookie.Value, &cookieValue); err == nil {
//fmt.Println(cookie)
cookieValue["userName"] = cookie.Value
//fmt.Println(cookieValue["userName"])
//}
/*else {
fmt.Println("Error ", err)
}*/
}
return cookieValue["userName"]
}
/*func GetFullName(request *http.Request) (fullName string) {
fmt.Println("In GetFullName")
cookieValue := make(map[string]string)
if cookie2, err := request.Cookie("session"); err == nil {
fmt.Println("cookieValue = ", cookie2.Value)
//if err = cookieHandler.Decode("session", cookie.Value, &cookieValue); err == nil {
fmt.Println(cookie2)
cookieValue["fullName"] = cookie2.Value
fmt.Println(cookieValue["fullName"])
//}
}
return cookieValue["fullName"]
}*/
func ClearSession(response http.ResponseWriter) {
cookie := &http.Cookie{
Name: "session",
Value: "",
Path: "/",
MaxAge: -1,
}
http.SetCookie(response, cookie)
}
代码中的注释问题。我想在PHP中使用会话。建议更好的方法来保护cookie并保持会话。也给出一些解释。
已编辑:解释cookieHandler.Encode()
和cookieHandler.Decode()
。它不会解码传递给它的数据。
答案 0 :(得分:3)
var retMap = make(map[string]string)
是一个全局地图,您可以读取和写入,这是不安全的:当您同时拥有多个用户时,您将覆盖此地图的内容。
您根本没有使用securecookie软件包对Cookie值进行编码 - 事实上,根本不清楚您在哪里使用它。
cookie := http.Cookie{
Name: "session",
// This should be encoded.
Value: sessionData["userName"], //Here i want map or something else that can accept multiple values
Expires: expiration,
//MaxAge: 3600,
}
包太多了:您有loginpackage
,sessionpackage
和package main
。套餐应该满足一个主题' - auth
包可能更有意义,甚至只需一个package main
,直到您更熟悉Go。
您没有对密码进行哈希处理 - 将纯文本密码存储在数据库中,并使用r.FormValue("password")
的值进行查找是非常不安全的。阅读本文,了解如何在Go:Golang/App Engine - securely hashing a user's password
您应该使用gorilla/sessions软件包而不是较低级别的securecookie软件包。
修改文档中的gorilla / sessions示例:
package main
import (
"net/http"
"github.com/gorilla/sessions"
)
// Use the CookieStore
var store = sessions.NewCookieStore([]byte("something-very-secret"))
func LoginOperation(w http.ResponseWriter, r *http.Request) {
// Your existing DB code - shorter to make the example here clearer
err := db.QueryRow("SELECT lvl_flag FROM admin_instance WHERE user_name = ? AND passwd = ?", r.FormValue("username"), r.FormValue("password")).Scan(&lvl)
// Don't use a global map - create a new one
userDetails := make(map[string]string)
userDetails["msg"] = "Login successfully"
userDetails["err"] = "Not Login"
userDetails["lvl"] = lvl
userDetails["fullName"] = uFullName
// Get a session (existing/new)
session, err := store.Get(r, "session-name")
if err != nil {
http.Error(w, err.Error(), 500)
return
}
// Set some session values.
session.Values["userDetails"] = userDetails
// Save it before we write to the response/return from the handler.
session.Save(r, w)
}
稍后,如果您想要检索详细信息:
func RequireAuth(w http.ResponseWriter, r *http.Request) {
// Get a session (existing/new)
session, err := store.Get(r, "session-name")
if err != nil {
http.Error(w, err.Error(), 500)
return
}
// Type assert our userDetails map out of the session's map[string]interface{}
userDetails, ok := session.Values["userDetails"].(map[string]string)
if !ok {
// User does not have an existing session - treat them as not logged in and/or re-direct them to your login page.
http.Error(w, http.StatusCode(401), 401)
return
}
// Check the user details - e.g. if userDetails["lvl"] == "ACTIVE" { ... }
// TODO
}