13

ゴリラ セッション Web ツールキットを使用している間、セッション変数はリクエスト間で維持されません。サーバーを起動して localhost:8100/ と入力すると、セッション値が存在しないため、ページが 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("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)
    }
}

誰かが私が間違っていることを教えてもらえますか? 前もって感謝します。

4

5 に答える 5

2

コメント チェーンに続いてDomain、セッション オプションから制約を削除するか、解決する FQDN に置き換えてみてください (/etc/hosts例を使用)。

これは、明示的な「localhost」ドメインを持つ Cookie が送信されない Chromium のバグのようです。この問題は、Firefox では発生していないようです。

を使用してデモを機能させることができました

store.Options = &sessions.Options{
    // Domain: "localhost",
    MaxAge:   3600 * 1, // 1 hour
    HttpOnly: true,
}
于 2014-02-19T04:20:16.437 に答える
2

私の場合、問題はパスでした。質問がそれに関するものではないことはわかっていますが、Google を検索すると、この投稿が最初に表示されます。したがって、次のようなパスでセッションを開始していました。

/usuario/login

そのため、パスは /usuario に設定され、その後、/Cookieから別のリクエストを行ったときに、 / が /usuario と同じではないため、設定されませんでした

パスを指定して修正しました。これは明らかなはずですが、気付くのに数時間かかりました。そう:

&sessions.Options{
        MaxAge:   60 * 60 * 24,
        HttpOnly: true,
        Path:     "/", // <-- This is very important
    }

一般的な Cookie の詳細: https://developer.mozilla.org/es/docs/Web/HTTP/Cookies

于 2019-10-25T15:46:49.893 に答える
0

「CookieStore」の代わりにサーバー側の「FilesystemStore」を使用して、セッション変数を保存します。もう 1 つの方法は、セッションをリクエストのコンテキスト変数として更新することです。つまり、セッションをコンテキストに保存し、ゴリラ/コンテキスト パッケージの context.Set() を使用して、ブラウザがすべてのリクエストでセッションを渡すようにします。

「CookieStore」を使用すると、Cookie に保存される情報の量が増えるにつれて、要求と応答ごとにネットワーク経由で送信される情報が増えるため、クライアントにとって負担が大きくなります。これが提供する利点は、サーバー側にセッション情報を保存する必要がないことです。セッション情報をサーバーに保存することが制約にならない場合、理想的な方法は、ログインおよび認証関連の情報をサーバー側の「非 Cookie」セッション ストアに保存し、トークンをクライアントに渡すことです。サーバーは、トークンとセッション情報のマップを維持します。「FilesystemStore」を使用すると、これを行うことができます。

「FilesystemStore」と「CookieStore」はどちらも「Store」インターフェースを実装していますが、それぞれの「Save()」関数の実装はわずかに異なります。関数CookieStore.Save()FilesystemStore.Save()の両方のソース コード「CookieStore」がセッション情報を保持できない理由を理解するのに役立ちます。FilesystemStore の Save() メソッドは、セッション情報を応答ヘッダーに書き込むだけでなく、サーバー側のセッション ファイルにも情報を保存します。「CookieStore」の実装では、ブラウザが次のリクエストへのレスポンスから新しく変更された Cookie を送信できない場合、リクエストは失敗する可能性があります。「FilesystemStore」実装では、ブラウザーに与えられるトークンは常に同じままです。セッション情報はファイル内で更新され、要求しているトークンに基づいて、必要に応じて取得されます。

于 2017-09-13T06:31:57.250 に答える