所以我尝试使用 Golang 的 OpenID 包,位于此处:https://github.com/yohcop/openid-go
在 _example
中它说它在内存存储中用于存储 nonce/discoverycache 信息并且它不会释放内存并且我应该使用某种方式实现我自己的版本数据库。
我选择的数据库是 MySQL,我尝试实现我认为正确的(但不是,没有给我任何编译错误,但在运行时崩溃)
我的 DiscoveryCache.go 是这样的:
package openid
import (
"database/sql"
"log"
//"time"
_ "github.com/go-sql-driver/mysql"
"github.com/yohcop/openid-go"
)
type SimpleDiscoveredInfo struct {
opEndpoint, opLocalID, claimedID string
}
func (s *SimpleDiscoveredInfo) OpEndpoint() string { return s.opEndpoint }
func (s *SimpleDiscoveredInfo) OpLocalID() string { return s.opLocalID }
func (s *SimpleDiscoveredInfo) ClaimedID() string { return s.claimedID }
type SimpleDiscoveryCache struct{}
func (s SimpleDiscoveryCache) Put(id string, info openid.DiscoveredInfo) {
/*
db, err := sql.Query("mysql", "db:connectinfo")
errCheck(err)
rows, err := db.Query("SELECT opendpoint, oplocalid, claimedid FROM discovery_cache")
errCheck(err)
was unsure what to do here because I'm not sure how to
return the info properly
*/
log.Println(info)
}
func (s SimpleDiscoveryCache) Get(id string) openid.DiscoveredInfo {
db, err := sql.Query("mysql", "db:connectinfo")
errCheck(err)
var sdi = new(SimpleDiscoveredInfo)
err = db.QueryRow("SELECT opendpoint, oplocalid, claimedid FROM discovery_cache WHERE id=?", id).Scan(&sdi)
errCheck(err)
return sdi
}
还有我的 Noncestore.go 包openid
import (
"database/sql"
"errors"
"flag"
"fmt"
"time"
_ "github.com/go-sql-driver/mysql"
)
var maxNonceAge = flag.Duration("openid-max-nonce-age",
60*time.Second,
"Maximum accepted age for openid nonces. The bigger, the more"+
"memory is needed to store used nonces.")
type SimpleNonceStore struct{}
func (s *SimpleNonceStore) Accept(endpoint, nonce string) error {
db, err := sql.Open("mysql", "dbconnectinfo")
errCheck(err)
if len(nonce) < 20 || len(nonce) > 256 {
return errors.New("Invalid nonce")
}
ts, err := time.Parse(time.RFC3339, nonce[0:20])
errCheck(err)
rows, err := db.Query("SELECT * FROM noncestore")
defer rows.Close()
now := time.Now()
diff := now.Sub(ts)
if diff > *maxNonceAge {
return fmt.Errorf("Nonce too old: %ds", diff.Seconds())
}
d := nonce[20:]
for rows.Next() {
var timeDB, nonce string
err := rows.Scan(&nonce, &timeDB)
errCheck(err)
dbTime, err := time.Parse(time.RFC3339, timeDB)
errCheck(err)
if dbTime == ts && nonce == d {
return errors.New("Nonce is already used")
}
if now.Sub(dbTime) < *maxNonceAge {
_, err := db.Query("INSERT INTO noncestore SET nonce=?, time=?", &nonce, dbTime)
errCheck(err)
}
}
return nil
}
func errCheck(err error) {
if err != nil {
panic("We had an error!" + err.Error())
}
}
然后我尝试在我的主文件中使用它们:
import _"github.com/mysqlOpenID"
var nonceStore = &openid.SimpleNonceStore{}
var discoveryCache = &openid.SimpleDiscoveryCache{}
我没有得到编译错误但是它崩溃了
我相信你会看到我的代码然后去他妈的(我是新手,只有一周左右的 Golang 经验,所以请随时纠正任何问题)
显然我做错了什么,我基本上在 github 上查看了 OpenId 上的 NonceStore.go 和 DiscoveryCache.go,复制了它,但是用数据库 insert
和 select 替换了 map
函数
如果有人能为我指明正确的方向以正确实现此功能,我将不胜感激,谢谢!如果您需要更多信息,请询问。
最佳答案
好的。首先,我不相信代码可以编译。
让我们看看一些错误,好吗?
db, err := sql.Open("mysql", "dbconnectinfo")
这一行打开一个数据库连接。它应该只使用一次,最好在 init()
函数中使用。例如,
var db *sql.DB
func init() {
var err error
// Now the db variable above is automagically set to the left value (db)
// of sql.Open and the "var err error" above is the right value (err)
db, err = sql.Open("mysql", "root@tcp(127.0.0.1:3306)")
if err != nil {
panic(err)
}
}
砰。现在您已连接到您的 MySQL 数据库。
现在呢?
这个(来自 Get)很恶心:
db, err := sql.Query("mysql", "db:connectinfo")
errCheck(err)
var sdi = new(SimpleDiscoveredInfo)
err = db.QueryRow("SELECT opendpoint, oplocalid, claimedid FROM discovery_cache WHERE id=?", id).Scan(&sdi)
errCheck(err)
相反,它应该是这样的:
// No need for a pointer...
var sdi SimpleDiscoveredInfo
// Because we take the address of 'sdi' right here (inside Scan)
// And that's a useless (and potentially problematic) layer of indirection.
// Notice how I dropped the other "db, err := sql.Query" part? We don't
// need it because we've already declared "db" as you saw in the first
// part of my answer.
err := db.QueryRow("SELECT ...").Scan(&sdi)
if err != nil {
panic(err)
}
// Return the address of sdi, which means we're returning a pointer
// do wherever sdi is inside the heap.
return &sdi
接下来是这个:
/*
db, err := sql.Query("mysql", "db:connectinfo")
errCheck(err)
rows, err := db.Query("SELECT opendpoint, oplocalid, claimedid FROM discovery_cache")
errCheck(err)
was unsure what to do here because I'm not sure how to
return the info properly
*/
如果您一直在注意,我们可以删除第一个 sql.Query
行。
太好了,现在我们只有:
行,错误 := db.Query("SELECT ...")
那么,为什么不做在 Accept
方法中所做的事情,并使用 for rows.Next()...
解析行呢?
关于mysql - 如何为使用 MySQL 数据库而不是内存存储的 OpenID 实现自己的接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32002070/