- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
我在使用 Gorilla session 处理程序在 Golang 中持久保存 session 时遇到了问题。类似的问题(未解决!)已在其他堆栈溢出问题中提出(此处:Sessions variables in golang not saved while using gorilla sessions 和此处:cannot get gorilla session value by key)。这非常可怕,因为看起来 1) 不仅仅是我 2) 目前似乎没有解决方案 3) Gorilla Sessions 包可能从根本上被破坏了。
这里是更详细的问题:
我可以在登录时设置 session 没有问题。但是,在我登录并向后端发出另一个请求后, session 值不会持久化,这意味着我无法提取 session 。例如,Value ['username'] (即使那是 session 的重点)。
所以:
A) 登录、写入 session 、检索 session.Value['usernames'] 并且一切正常。
B) 导航到前端的另一个页面并向后端发出另一个请求(创建一个新角色)。
C) 尝试检索 session.Value['username']。是零!!!!!!
这是用户在后端导航以登录的流程 -
首先是 session 处理程序:
package config
import (
"log"
"net/http"
"github.com/gorilla/sessions"
)
type Options struct {
Path string
Domain string
MaxAge int
Secure bool
HttpOnly bool
}
type Session struct {
ID string
Values map[interface{}]interface{}
Options *Options
IsNew bool
}
type Store interface {
Get(r *http.Request, name string) (*sessions.Session, error)
New(r *http.Request, name string) (*sessions.Session, error)
Save(r *http.Request, w http.ResponseWriter, s *sessions.Session) error
}
var SessionsStore = sessions.NewCookieStore([]byte("secret"))
func init() {
SessionsStore.Options = &sessions.Options{
Domain: "localhost",
Path: "/",
MaxAge: 3600 * 8, // 8 hours
HttpOnly: true,
}
}
func KeyStore() (store Store) {
log.Print("inside KeyStore")
store = SessionsStore
log.Print("Value of store is : ", store)
return store
}
接下来,这是我如何从 main 到路由到我的每个组件:
主要
package main
import (
"database/sql"
"fmt"
"log"
"net/http"
"os"
_ "github.com/lib/pq"
"github.com/patientplatypus/gorest/config"
"github.com/gorilla/handlers"
)
const (
host = "localhost"
port = 5432
user = "patientplatypus"
password = "superdupersecretyo"
dbname = "dungeon_world"
)
func main() {
psqlInfo := fmt.Sprintf("host=%s port=%d user=%s "+
"password=%s dbname=%s sslmode=disable",
"localhost", 5432, "patientplatypus", "supersecret", "dungeon_world")
var err error
config.DB, err = sql.Open("postgres", psqlInfo)
if err != nil {
panic(err)
}
err = config.DB.Ping()
if err != nil {
panic(err)
}
fmt.Println("Successfully connected~!")
router := NewRouter()
os.Setenv("ORIGIN_ALLOWED", "*")
headersOk := handlers.AllowedHeaders([]string{"X-Requested-With", "Content-Type"})
originsOk := handlers.AllowedOrigins([]string{os.Getenv("ORIGIN_ALLOWED")})
methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "OPTIONS"})
log.Fatal(http.ListenAndServe(":8080", handlers.CORS(originsOk, headersOk, methodsOk)(router)))
}
这里是路由到每个处理程序的路由包:
package main
import (
"net/http"
"github.com/patientplatypus/gorest/users"
"github.com/patientplatypus/gorest/dungeon_db"
"github.com/patientplatypus/gorest/character"
"github.com/patientplatypus/gorest/createcharacter"
"github.com/gorilla/mux"
)
type Route struct {
Name string
Method string
Pattern string
HandlerFunc http.HandlerFunc
}
type Routes []Route
func NewRouter() *mux.Router {
router := mux.NewRouter().StrictSlash(true)
for _, route := range routes {
router.
Methods(route.Method).
Path(route.Pattern).
Name(route.Name).
Handler(route.HandlerFunc)
}
return router
}
var routes = Routes{
Route{
"ClassType",
"POST",
"/character/class",
character.ClassType,
},
<MORE ROUTES FOLLOWING SAME PATTERN>
}
现在这里是登录功能。这是我编写原始 session 并打印出 session.Values['username'] 以表明它有效的地方:
package users
import (
"encoding/json"
"log"
"net/http"
"github.com/patientplatypus/gorest/config"
)
type LoginResponse struct {
Status string
}
type User struct {
Username string
Password string
Id int
}
func UserLogin(w http.ResponseWriter, r *http.Request) {
decoder := json.NewDecoder(r.Body)
var incomingjson User
err := decoder.Decode(&incomingjson)
if err != nil {
panic(err)
}
username := incomingjson.Username
password := incomingjson.Password
log.Print("username: ", username)
log.Print("password: ", password)
if username != "" && password != "" {
incomingjson.Login(w, r)
} else {
fmt.Fprintln(w, "error username or password is blank!")
}
}
func (incomingjson *User) Login(w http.ResponseWriter, r *http.Request) {
session, _ := config.KeyStore().Get(r, "cookie-name")
log.Print("loginjson: ", incomingjson)
var tempvar string
err := config.DB.QueryRow("SELECT username FROM users WHERE username=$1;", incomingjson.Username).Scan(&tempvar)
log.Print("err: ", err)
if err == nil {
// 1 row
log.Print("Found username")
var passwordindatabase string
config.DB.QueryRow("SELECT password FROM users WHERE username=$1;", &incomingjson.Username).Scan(&passwordindatabase)
if passwordindatabase == incomingjson.Password {
log.Print("username and password match!")
session.Values["authenticated"] = true
session.Values["username"] = incomingjson.Username
config.KeyStore().Save(r, w, session)
response := LoginResponse{Status: "Success, user logged in"}
json.NewEncoder(w).Encode(response)
} else {
log.Print("username and password don't match!")
session.Values["authenticated"] = false
session.Values["username"] = ""
config.KeyStore().Save(r, w, session)
response := LoginResponse{Status: "Failure, username and password don't match"}
json.NewEncoder(w).Encode(response)
}
} else {
//empty result or error
log.Print("Username not found or there was an error: ", err)
response := LoginResponse{Status: "User not found!"}
json.NewEncoder(w).Encode(response)
}
}
现在是问题组件。它的工作是在检查用户是否存在后创建一个新角色(sessioncheck 可以)...
所以这里我有:
package createcharacter
import (
"encoding/json"
"log"
"net/http"
"github.com/patientplatypus/gorest/config"
)
var Username string
var Checkok bool
func SessionsCheck(w http.ResponseWriter, r *http.Request) (username string, checkok bool) {
store := config.KeyStore()
session, _ := store.Get(r, "cookie-name")
log.Print("inside sessionscheck...what is the value of stuff....")
log.Print("session: ", session)
log.Print("session.Values: ", session.Values)
log.Print("username: ", session.Values["username"])
log.Print("authenticated: ", session.Values["authenticated"])
if session.Values["username"] == nil {
if session.Values["authenticated"] == false {
log.Print("Verboten!")
http.Error(w, "Forbidden", http.StatusForbidden)
return "nil", false
}
}
return session.Values["username"].(string), true
}
func NewCharacter(w http.ResponseWriter, r *http.Request) {
Username, Checkok = SessionsCheck(w, r)
<FUNCTION CONTINUES>
这是我收到错误的地方...但我不知道如何修复。
终端输出为:
2017/10/15 15:08:56 inside KeyStore
2017/10/15 15:08:56 Value of store is : &{[0xc42010c000] 0xc42007d5f0}
2017/10/15 15:08:56 inside sessionscheck...what is the value of stuff....
2017/10/15 15:08:56 session: &{ map[] 0xc4201316b0 true 0xc4200e0a80 cookie-name}
2017/10/15 15:08:56 session.Values: map[]
2017/10/15 15:08:56 username: <nil>
2017/10/15 15:08:56 authenticated: <nil>
2017/10/15 15:08:56 http: panic serving [::1]:53668: interface conversion: interface {} is nil, not string
goroutine 13 [running]:
net/http.(*conn).serve.func1(0xc42015c5a0)
/usr/local/opt/go/libexec/src/net/http/server.go:1697 +0xd0
panic(0x133bcc0, 0xc420061f00)
/usr/local/opt/go/libexec/src/runtime/panic.go:491 +0x283
github.com/patientplatypus/gorest/createcharacter.SessionsCheck(0x1540d00, 0xc42010a540, 0xc42014ea00, 0xc42011ab00, 0x3, 0xc420001680)
/Users/patientplatypus/Documents/golang/src/github.com/patientplatypus/gorest/createcharacter/charactercontroller.go:31 +0x5c9
github.com/patientplatypus/gorest/createcharacter.NewCharacter(0x1540d00, 0xc42010a540, 0xc42014ea00)
/Users/patientplatypus/Documents/golang/src/github.com/patientplatypus/gorest/createcharacter/charactercontroller.go:35 +0x5a
net/http.HandlerFunc.ServeHTTP(0x13b8690, 0x1540d00, 0xc42010a540, 0xc42014ea00)
/usr/local/opt/go/libexec/src/net/http/server.go:1918 +0x44
github.com/gorilla/mux.(*Router).ServeHTTP(0xc420066360, 0x1540d00, 0xc42010a540, 0xc42014ea00)
/Users/patientplatypus/Documents/golang/src/github.com/gorilla/mux/mux.go:133 +0xed
github.com/gorilla/handlers.(*cors).ServeHTTP(0xc42010c7e0, 0x1540d00, 0xc42010a540, 0xc42014e800)
/Users/patientplatypus/Documents/golang/src/github.com/gorilla/handlers/cors.go:118 +0x5c8
net/http.serverHandler.ServeHTTP(0xc42014a000, 0x1540d00, 0xc42010a540, 0xc42014e800)
/usr/local/opt/go/libexec/src/net/http/server.go:2619 +0xb4
net/http.(*conn).serve(0xc42015c5a0, 0x1541240, 0xc420061dc0)
/usr/local/opt/go/libexec/src/net/http/server.go:1801 +0x71d
created by net/http.(*Server).Serve
/usr/local/opt/go/libexec/src/net/http/server.go:2720 +0x288
很抱歉冗长,但我认为这是我可以从我的代码库中重现的最简单的示例。如果有人有任何建议,请告诉我。
编辑:
我注意到的一件事如下:
2017/10/15 15:08:56 session: &{ map[] 0xc4201316b0 true 0xc4200e0a80 cookie-name}
2017/10/15 15:08:56 session.Values: map[]
似乎表明用户名和经过身份验证的 (true 0xc4200e0a80) 存储在 session.Values []map 函数的外部。这是为什么?
编辑编辑:
所以...我认为我编写 config.KeyStore() 的方式可能有问题,所以我将其重写为以下内容并在整个项目中坚持使用:
package config
import (
"github.com/gorilla/sessions"
)
var SessionsStore = sessions.NewCookieStore([]byte("secret"))
func init() {
SessionsStore.Options = &sessions.Options{
Domain: "localhost",
Path: "/",
MaxAge: 3600 * 8, // 8 hours
HttpOnly: true,
}
}
所以现在只要我需要 SessionsStore,我就调用 conf.SessionsStore。这似乎是我认为可行的规范方法。我仍然有同样的问题。
最佳答案
package main
import (
"fmt"
"log"
"net/http"
"time"
"github.com/gorilla/mux"
"github.com/gorilla/sessions"
)
const appCookie = "myappcookies"
var cookies *sessions.CookieStore
func Login(w http.ResponseWriter, r *http.Request) {
//
// For the sake of simplicity, I am using a global here.
// You should be using a context.Context instead!
session, err := cookies.Get(r, appCookie)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
log.Println(err)
return
}
session.Values["userName"] = "StackOverflow"
session.Save(r, w)
}
func Session(w http.ResponseWriter, r *http.Request) {
session, err := cookies.Get(r, appCookie)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
log.Println(err)
return
}
w.Write([]byte(fmt.Sprintf("Objects in session: %d\n", len(session.Values))))
for k, v := range session.Values {
w.Write([]byte(fmt.Sprintf("Key=%v, Value=%v\n", k, v)))
}
}
func main() {
cookies = sessions.NewCookieStore([]byte("mysuperdupersecret"))
router := mux.NewRouter()
router.Path("/login").Methods(http.MethodPost).HandlerFunc(Login)
router.Path("/session").Methods(http.MethodGet).HandlerFunc(Session)
server := &http.Server{
Handler: router,
Addr: ":8000",
// Good practice: enforce timeouts for servers you create!
WriteTimeout: 15 * time.Second,
ReadTimeout: 15 * time.Second,
}
log.Fatal(server.ListenAndServe())
}
关于session - Gorilla session 不会在 Golang 中持续存在,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46759540/
尝试使用集成到 QTCreator 的表单编辑器,但即使我将插件放入 QtCreator.app/Contents/MacOS/designer 也不会显示。不过,相同的 dylib 文件确实适用于独
在此代码示例中。 “this.method2();”之后会读到什么?在返回returnedValue之前会跳转到method2()吗? public int method1(int returnedV
我的项目有通过gradle配置的依赖项。我想添加以下依赖项: compile group: 'org.restlet.jse', name: 'org.restlet.ext.apispark', v
我将把我们基于 Windows 的客户管理软件移植到基于 Web 的软件。我发现 polymer 可能是一种选择。 但是,对于我们的使用,我们找不到 polymer 组件具有表格 View 、下拉菜单
我的项目文件夹 Project 中有一个文件夹,比如 ED 文件夹,当我在 Eclipse 中指定在哪里查找我写入的文件时 File file = new File("ED/text.txt"); e
这是奇怪的事情,这个有效: $('#box').css({"backgroundPosition": "0px 250px"}); 但这不起作用,它只是不改变位置: $('#box').animate
这个问题在这里已经有了答案: Why does OR 0 round numbers in Javascript? (3 个答案) 关闭 5 年前。 Mozilla JavaScript Guide
这个问题在这里已经有了答案: Is the function strcmpi in the C standard libary of ISO? (3 个答案) 关闭 8 年前。 我有一个问题,为什么
我目前使用的是共享主机方案,我不确定它使用的是哪个版本的 MySQL,但它似乎不支持 DATETIMEOFFSET 类型。 是否存在支持 DATETIMEOFFSET 的 MySQL 版本?或者有计划
研究 Seam 3,我发现 Seam Solder 允许将 @Named 注释应用于包 - 在这种情况下,该包中的所有 bean 都将自动命名,就好像它们符合条件一样@Named 他们自己。我没有看到
我知道 .append 偶尔会增加数组的容量并形成数组的新副本,但 .removeLast 会逆转这种情况并减少容量通过复制到一个新的更小的数组来改变数组? 最佳答案 否(或者至少如果是,则它是一个错
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
noexcept 函数说明符是否旨在 boost 性能,因为生成的对象中可能没有记录异常的代码,因此应尽可能将其添加到函数声明和定义中?我首先想到了可调用对象的包装器,其中 noexcept 可能会产
我正在使用 Angularjs 1.3.7,刚刚发现 Promise.all 在成功响应后不会更新 angularjs View ,而 $q.all 会。由于 Promises 包含在 native
我最近发现了这段JavaScript代码: Math.random() * 0x1000000 10.12345 10.12345 >> 0 10 > 10.12345 >>> 0 10 我使用
我正在编写一个玩具(物理)矢量库,并且遇到了 GHC 坚持认为函数应该具有 Integer 的问题。是他们的类型。我希望向量乘以向量以及标量(仅使用 * ),虽然这可以通过仅使用 Vector 来实现
PHP 的 mail() 函数发送邮件正常,但 Swiftmailer 的 Swift_MailTransport 不起作用! 这有效: mail('user@example.com', 'test
我尝试通过 php 脚本转储我的数据,但没有命令行。所以我用 this script 创建了我的 .sql 文件然后我尝试使用我的脚本: $link = mysql_connect($host, $u
使用 python 2.6.4 中的 sqlite3 标准库,以下查询在 sqlite3 命令行上运行良好: select segmentid, node_t, start, number,title
我最近发现了这段JavaScript代码: Math.random() * 0x1000000 10.12345 10.12345 >> 0 10 > 10.12345 >>> 0 10 我使用
我是一名优秀的程序员,十分优秀!