使用大猩猩会话时,golang中的会话变量未保存 [英] Sessions variables in golang not saved while using gorilla sessions

查看:163
本文介绍了使用大猩猩会话时,golang中的会话变量未保存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用大猩猩会话Web工具包时,会话变量不会通过请求进行维护。
当我启动服务器并输入localhost:8100 / page被定向到login.html,因为会话值不存在。在我登录后,我在存储中设置了会话变量,页面被重定向到home.html。但是,当我打开一个新标签并键入localhost:8100 /页面时,应该使用已经存储的会话变量将页面定向到home.html,但是页面会被重定向到login.html。
以下是代码。

  package main 

import(
crypto / md5
encoding / hex
fmt
github.com/gocql/gocql
github.com/gorilla/mux
github.com/gorilla/sessions
net / http
time


var store = sessions.NewCookieStore([] byte( )

var router = mux.NewRouter()

func init(){

store.Options =& amp; ; sessions.Options {
域名:localhost,
路径:/,
MaxAge:3600 * 1,// 1小时
HttpOnly:true,


func main(){
//会话处理
router.HandleFunc(/,SessionHandler)
router.HandleFunc(/ signIn ,SignInHandler)
router.HandleFunc(/ signUp,SignUpHandler)
router.HandleFunc(/ logOut,LogOutHandler)
http.Handle(/,router)
http.ListenAndServe(:8100,零)
}

// signIn
的处理程序func SignInHandler(res http.ResponseWriter,req * http.Request){

email:= req.FormValue(email)
密码:= req.FormValue(密码)

//生成密码哈希
hasher:= md5.New()
hasher.Write([] byte密码))
encrypted_pa​​ssword:= hex.EncodeToString(hasher.Sum(nil))
$ b $ cassandra连接
cluster:= gocql.NewCluster(localhost)
cluster.Keyspace =gbuy
cluster.DefaultPort = 9042
cluster.Consistency = gocql.Quorum
session,_:= cluster.CreateSession()
推迟会话。关闭()

//选择查询
var firstname字符串
stmt:=选择名字FROM USER WHERE email ='+ email +'and password ='+ encrypted_pa​​ssword +';
err:= session.Query(stmt).Scan(& firstname)
if err!= nil {
fmt.Fprintf(res,failed)
} else {
if firstname =={
fmt.Fprintf(res,failed)
} else {
fmt.Fprintf(res,firstname)
}
}

//存储会话变量
sessionNew,_:= store.Get(req,loginSession)

//设置一些会话值。
sessionNew.Values [email] = email
sessionNew.Values [name] =名字

//保存。
sessionNew.Save(req,res)
//store.Save(req,res,sessionNew)

fmt.Println(记录后的会话:)
fmt.Println(sessionNew)

}

// signUp
的处理程序func SignUpHandler(res http.ResponseWriter,req * http.Request){

fName:= req.FormValue(fName)
lName:= req.FormValue(lName)
email:= req.FormValue(email)
密码:= req.FormValue(passwd)
birthdate:= req.FormValue(date)
city:= req.FormValue(city)
gender:= req .FormValue(gender)

//获取当前时间戳并对其进行格式化。
sysdate:= time.Now()。格式(2006-01-02 15:04:05-0700)

//生成密码的散列
hasher: = md5.New()
hasher.Write([] byte(password))
encrypted_pa​​ssword:= hex.EncodeToString(hasher.Sum(nil))

// cassandra连接
cluster:= gocql.NewCluster(localhost)
cluster.Keyspace =gbuy
cluster.DefaultPort = 9042
cluster.Consistency = gocql.Quorum
会话,_:= cluster.CreateSession()
推迟session.Close()

//将数据插入表中
stmt:=INSERT INTO USER(email ,姓氏,姓氏,出生日期,城市,性别,密码,creation_date)VALUES(''+ email +'','+ fName +','+ lName +','+ birthdate +',' + city +','+ gender +','+ encrypted_pa​​ssword +','+ sysdate +');
fmt.Println(stmt)
err:= session.Query(stmt).Exec()
if err!= nil {
fmt.Fprintf(res,failed )
} else {
fmt.Fprintf(res,fName)
}
}

// logOut的处理程序
func LogOutHandler (会话注销)

fmt.Println(session in logout)$
sessionOld,err:= store.Get(req,loginSession)

fmt.Println b $ b fmt.Println(sessionOld)
if err = sessionOld.Save(req,res); err!= nil {
fmt.Println(保存会话出错:%v,err)
}
}

// Session $ b $的处理程序b func SessionHandler(res http.ResponseWriter,req * http.Request){

router.PathPrefix(/)。Handler(http.FileServer(http.Dir(../ static /) )))
session,_:= store.Get(req,loginSession)

fmt.Println(SessionHandler中的会话)
fmt.Println(session)


如果val,ok:= session.Values [email]。(string); OK {
//如果val是一个字符串
switch val {
case:{
http.Redirect(res,req,html / login.html,http .StatusFound)}
默认值:
http.Redirect(res,req,html / home.html,http.StatusFound)
}
} else {
//如果val不是字符串类型
http.Redirect(res,req,html / login.html,http.StatusFound)
}
}

有人可以告诉我我做错了什么。

首先,:你永远不应该使用md5来散列密码。 阅读这篇文章为什么,然后使用Go的 bcrypt软件包。你也应该参数化你的SQL查询,否则您打开灾难性 SQL注入攻击。



无论如何:您需要解决的几个问题:




  • 您的会话不是粘住的是您要设置路径作为 / loginSession - 因此,当用户访问任何其他路径(即 / )时,会话不是



您应该在程序初始化时设置一个会话存储并在其中设置选项:

  var store = sessions.NewCookieStore([] byte(something-very-secret))

func init ){

store.Options =& sessions.Options {
域名:localhost,
路径:/,
MaxAge:3600 * 8, // 8小时
HttpOnly:true,
}


$ b

你可能设置一个更具体的路径的原因是,如果登录的用户总是在子路由之内,比如 /帐户。在您的情况中,这不是发生了什么。



我应该在Web Inspector(资源> Cookie)中添加Chrome的资源选项卡,对于调试这些问题非常有用因为你可以看到cookie过期,路径和其他设置。




  • 您还正在检查 session.Values [ email] == nil ,这不起作用。 Go中的空字符串只是,因为 session.Values 映射[string] interface {} ,您需要键入断言字符串的值:




    pre $ $ code> if val,ok:= session.Values [email]。(string); OK {
    //如果val是一个字符串
    switch val {
    case:
    http.Redirect(res,req,html / login.html,http。 StatusFound)
    默认值:
    http.Redirect(res,req,html / home.html,http.StatusFound)
    }
    } else {
    //如果val不是字符串类型
    http.Redirect(res,req,html / login.html,http.StatusFound)
    }

我们处理不是字符串的情况,因此如果会话不符合我们的预期(客户端对其进行了修改,或者旧版本的程序使用了不同的类型)。




  • 保存会话时,您不检查错误。

      sessionNew.Save(req,res)




...应该是:

  err:= sessionNew.Save(req,res)
if err!= nil {
// han dle the error case
}




  • 您应该在使用静态文件之前在 SessionHandler 中获取/验证会话(然而,以非常迂回的方式进行):

    b
    $ b

      func SessionHandler(res http.ResponseWriter,req * http.Request){
    session,err:= store.Get(req,如果session.Values [email] == nil {$ b //处理错误
    }

    $ b http.Redirect(res,req,html / login.html,http.StatusFound)
    } else {
    http.Redirect(res,req,html / home.html,http .StatusFound)
    }
    //这不应该在这里 - 路由器不在此功能范围内!你应该在main()中设置它,并用一个检查有效会话的函数来包装它。
    router.PathPrefix(/)。Handler(http.FileServer(http.Dir(../ static /)))
    }



Session Variables are not maintained across request while using gorilla sessions web toolkit. When I start the server and type localhost:8100/ page is directed to login.html since session values do not exist.After I login I set the session variable in the store and the page is redirected to home.html. But when I open a new tab and type localhost:8100/ the page should be directed to home.html using already stored session variables, but the page is instead redirected to login.html. Following is the code.

    package main

import (
    "crypto/md5"
    "encoding/hex"
    "fmt"
    "github.com/gocql/gocql"
    "github.com/gorilla/mux"
    "github.com/gorilla/sessions"
    "net/http"
    "time"
)

var store = sessions.NewCookieStore([]byte("something-very-secret"))

var router = mux.NewRouter()

func init() {

    store.Options = &sessions.Options{
        Domain:   "localhost",
        Path:     "/",
        MaxAge:   3600 * 1, // 1 hour
        HttpOnly: true,
    }
}
func main() {
    //session handling
    router.HandleFunc("/", SessionHandler)
    router.HandleFunc("/signIn", SignInHandler)
    router.HandleFunc("/signUp", SignUpHandler)
    router.HandleFunc("/logOut", LogOutHandler)
    http.Handle("/", router)
    http.ListenAndServe(":8100", nil)
}

//handler for signIn
func SignInHandler(res http.ResponseWriter, req *http.Request) {

    email := req.FormValue("email")
    password := req.FormValue("password")

    //Generate hash of password
    hasher := md5.New()
    hasher.Write([]byte(password))
    encrypted_password := hex.EncodeToString(hasher.Sum(nil))

    //cassandra connection
    cluster := gocql.NewCluster("localhost")
    cluster.Keyspace = "gbuy"
    cluster.DefaultPort = 9042
    cluster.Consistency = gocql.Quorum
    session, _ := cluster.CreateSession()
    defer session.Close()

    //select query
    var firstname string
    stmt := "SELECT firstname FROM USER WHERE email= '" + email + "' and password ='" + encrypted_password + "';"
    err := session.Query(stmt).Scan(&firstname)
    if err != nil {
        fmt.Fprintf(res, "failed")
    } else {
        if firstname == "" {
            fmt.Fprintf(res, "failed")
        } else {
            fmt.Fprintf(res, firstname)
        }
    }

    //store in session variable
    sessionNew, _ := store.Get(req, "loginSession")

    // Set some session values.
    sessionNew.Values["email"] = email
    sessionNew.Values["name"] = firstname

    // Save it.
    sessionNew.Save(req, res)
    //store.Save(req,res,sessionNew)

    fmt.Println("Session after logging:")
    fmt.Println(sessionNew)

}

//handler for signUp
func SignUpHandler(res http.ResponseWriter, req *http.Request) {

    fName := req.FormValue("fName")
    lName := req.FormValue("lName")
    email := req.FormValue("email")
    password := req.FormValue("passwd")
    birthdate := req.FormValue("date")
    city := req.FormValue("city")
    gender := req.FormValue("gender")

    //Get current timestamp and format it.
    sysdate := time.Now().Format("2006-01-02 15:04:05-0700")

    //Generate hash of password
    hasher := md5.New()
    hasher.Write([]byte(password))
    encrypted_password := hex.EncodeToString(hasher.Sum(nil))

    //cassandra connection
    cluster := gocql.NewCluster("localhost")
    cluster.Keyspace = "gbuy"
    cluster.DefaultPort = 9042
    cluster.Consistency = gocql.Quorum
    session, _ := cluster.CreateSession()
    defer session.Close()

    //Insert the data into the Table
    stmt := "INSERT INTO USER (email,firstname,lastname,birthdate,city,gender,password,creation_date) VALUES ('" + email + "','" + fName + "','" + lName + "','" + birthdate + "','" + city + "','" + gender + "','" + encrypted_password + "','" + sysdate + "');"
    fmt.Println(stmt)
    err := session.Query(stmt).Exec()
    if err != nil {
        fmt.Fprintf(res, "failed")
    } else {
        fmt.Fprintf(res, fName)
    }
}

//handler for logOut
func LogOutHandler(res http.ResponseWriter, req *http.Request) {
    sessionOld, err := store.Get(req, "loginSession")

    fmt.Println("Session in logout")
    fmt.Println(sessionOld)
    if err = sessionOld.Save(req, res); err != nil {
        fmt.Println("Error saving session: %v", err)
    }
}

//handler for Session
func SessionHandler(res http.ResponseWriter, req *http.Request) {

    router.PathPrefix("/").Handler(http.FileServer(http.Dir("../static/")))
    session, _ := store.Get(req, "loginSession")

    fmt.Println("Session in SessionHandler")
    fmt.Println(session)


    if val, ok := session.Values["email"].(string); ok {
        // if val is a string
        switch val {
        case "": {
            http.Redirect(res, req, "html/login.html", http.StatusFound) }
        default:
            http.Redirect(res, req, "html/home.html", http.StatusFound)
        }
    } else {
        // if val is not a string type
        http.Redirect(res, req, "html/login.html", http.StatusFound)
    }
}

Can somebody tell me what I am doing wrong. Thanks in advance.

解决方案

First up: you should never, ever, use md5 to hash passwords. Read this article on why, and then use Go's bcrypt package. You should also parameterise your SQL queries else you are open to catastrophic SQL injection attacks.

Anyway: there are a few problems you need to address here:

  • Your sessions aren't "sticking" is that you're setting the Path as /loginSession - so when a user visits any other path (i.e. /), the session isn't valid for that scope.

You should be setting up a session store on program initialisation and setting the options there:

var store = sessions.NewCookieStore([]byte("something-very-secret"))

func init() {

   store.Options = &sessions.Options{
    Domain:   "localhost",
    Path:     "/",
    MaxAge:   3600 * 8, // 8 hours
    HttpOnly: true,
}

The reason you might set a more specific path is if logged in users are always within a sub-route like /accounts. In your case, that's not what's happening.

I should add that Chrome's "Resource" tab in the Web Inspector (Resources > Cookies) is incredibly useful for debugging issues like these as you can see the cookie expiry, path and other settings.

  • You're also checking session.Values["email"] == nil, which doesn't work. An empty string in Go is just "", and because session.Values is a map[string]interface{}, you need to type assert the value to a string:

i.e.

if val, ok := session.Values["email"].(string); ok {
      // if val is a string
      switch val {
             case "":
                 http.Redirect(res, req, "html/login.html", http.StatusFound)
             default:
                 http.Redirect(res, req, "html/home.html", http.StatusFound)
      }
    } else {
        // if val is not a string type
        http.Redirect(res, req, "html/login.html", http.StatusFound)
    }

We deal with the "not a string" case so we're explicit about what the program should do if the session is not how we expected (client modified it, or an older version of our program used a different type).

  • You are not checking errors when saving your sessions.

    sessionNew.Save(req, res)
    

... should be:

    err := sessionNew.Save(req, res)
    if err != nil {
            // handle the error case
    }

  • You should get/validate the session in SessionHandler before serving static files (you are doing it in a very roundabout way, however):

    func SessionHandler(res http.ResponseWriter, req *http.Request) {
        session, err := store.Get(req, "loginSession")
        if err != nil {
            // Handle the error
        }
    
        if session.Values["email"] == nil {
            http.Redirect(res, req, "html/login.html", http.StatusFound)
        } else {
           http.Redirect(res, req, "html/home.html", http.StatusFound)
        }
        // This shouldn't be here - router isn't scoped in this function! You should set this in your main() and wrap it with a function that checks for a valid session.
        router.PathPrefix("/").Handler(http.FileServer(http.Dir("../static/")))
    }
    

这篇关于使用大猩猩会话时,golang中的会话变量未保存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆