本文介绍了我如何实现我自己的OpenID接口,它使用MySQL数据库而不是内存存储的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 因此,我正在尝试为Golang使用OpenID包: https:// github。 com / yohcop / openid-go 在 _example 中,它表示它在内存中使用用于存储nonce / discoverycache信息,并且它不会释放内存,我应该使用某种数据库来实现我自己的版本。 我选择的数据库是MySQL,我试图实现我认为是正确的(但不是,不给我任何编译错误,但在运行时崩溃) 我的DiscoveryCache.go是这样的: 包openid 导入(数据库/ sqllog //time _github.com/go-sql-driver/mysqlgithub.com/yohcop/openid-去) 类型SimpleDiscoveredInfo结构{ opEndpoint,opLocalID,claimsID字符串} func(s * SimpleDisco veredInfo)OpEndpoint()string {return s.opEndpoint} func(s * SimpleDiscoveredInfo)OpLocalID()string {return s.opLocalID} func(s * SimpleDiscoveredInfo)ClaimedID()string {return s。声明ID} 类型SimpleDiscoveryCache结构{} func(s SimpleDiscoveryCache)Put(id字符串,信息openid.DiscoveredInfo){ / * db ,err:= sql.Query(mysql,db:connectinfo) errCheck(err)$ b $ rows,err:= db.Query(SELECT opendpoint,oplocalid,claimsid FROM discovery_cache) errCheck(err) 不确定在这里做什么,因为我不确定如何正确返回信息 * / log.Println(info)} func(s SimpleDiscoveryCache)获取(id字符串)openid.DiscoveredInfo {$ b $ db,err:= sql.Query(mysql ,db:connectinfo) errCheck(err) var sdi = new(SimpleDiscoveredInfo) err = db.QueryRow(SELECT opendpoint,opl ocalid,claimid FROM discovery_cache WHERE id =?,id).Scan(& sdi) errCheck(err) return sdi } 和我的Noncestore.go 包openid 标记fmt时间错误 _github.com/go-sql-driver/mysql) var maxNonceAge = flag.Duration(openid-max-nonce-age , 60 * time.Second,openid临时值的最大接受时间。 ) 类型SimpleNonceStore结构{} func(s * SimpleNonceStore)接受更多的+ 内存(端点,nonce字符串)错误{ 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) $ b $ row,err:= db.Query(SELECT * FROM noncestore)推迟rows.Close() now:= time.Now() diff:= now.Sub(ts) if diff> * maxNonceAge { return fmt.Errorf(Nonce too old:%ds,diff.Seconds())} $ bd:= nonce [20:] for rows.Next(){ var timeDB,nonce string $ b $ 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)} } 返回nil } func errCheck(错误错误){ if err!= nil { panic(我们有错误!+ err.Error())} } 然后我尝试在我的主文件中使用它们: import _github.com/ mysqlOpenID var nonceStore =& openid.SimpleNonceStore {} var discoveryCache =& openid.SimpleDiscoveryCache {} 我没有得到编译错误,但崩溃了 我相信你会看看我的代码,地狱(我是相当新的,只有一个星期左右的经验与Golang,所以请随时纠正任何事情) 显然我做错了,我基本上查看了Op。的github上的NonceStore.go和DiscoveryCache.go enId复制它,但用数据库插入和选择函数替换映射 如果任何人都可以指出我正确的方向,如何正确实施这将是非常感谢,谢谢!如果您需要更多信息,请询问。 好的。首先,我不相信你的代码编译。 让我们看看一些错误,我们可以吗? db,err:= sql.Open(mysql,dbconnectinfo) 这一行打开一个数据库连接。它只能使用一次,最好在 init()函数中使用。例如, var db * sql.DB func init(){ var err error //现在上面的db变量被自动设置为sql.Open的左边值(db) //上面的var err error是正确的值(err) db,err = sql.Open(mysql,root @ tcp(127.0.0.1:3306)) if err!= nil { panic(err) } } Bang。现在你连接到你的MySQL数据库。 现在是什么? gross: db,err:= sql.Query(mysql,db:connectinfo) errCheck (错误) var sdi = new(SimpleDiscoveredInfo) err = db.QueryRow(SELECT opendpoint,oplocalid,claimsid FROM discovery_cache WHERE id =?,id).Scan(& sdi) errCheck(err) 相反,它应该是这样的: //不需要指针... var sdi SimpleDiscoveredInfo //因为我们'sdi'的地址在这里(扫描内) //这是一个无用的(可能有问题的)间接层。 //注意我如何删除其他的db,err:= sql.Query部分?我们不需要 //因为我们已经在第一个 // //部分答案中看到了声明db。 err:= db.QueryRow(SELECT ...)。Scan(& sdi) if err!= nil { panic(err)} //返回sdi的地址,这意味着我们返回一个指针 // do sid在堆内部。 return& sdi 接下来是这样的: / * db,err:= sql.Query(mysql,db:connectinfo) errCheck(err) rows,err:= db.Query(SELECT opendpoint,oplocalid,claimsid FROM discovery_cache) errCheck(err) 不确定在这里做什么,因为我不是确定如何正确返回信息 * / 如果您已经我们可以放弃第一个 sql.Query 行。 好极了,现在我们只有: rows,err:= db.Query(SELECT ...) 那么,为什么不做你在 Accept 方法中做的事情,并且使用来分析行。 Next()... ? So I'm trying to use the OpenID package for Golang, located here: https://github.com/yohcop/openid-goIn the _example it says that it uses in memory storage for storing the nonce/discoverycache information and that it will not free the memory and that I should implement my own version of them using some sort of database.My database of choice is MySQL, I have tried to implement what I thought was correct (but is not, does not give me any compile errors, but crashes on runtime)My DiscoveryCache.go is as such:package openidimport ( "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}And my Noncestore.go package openidimport ( "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()) }}Then I try to use them in my main file as:import _"github.com/mysqlOpenID"var nonceStore = &openid.SimpleNonceStore{}var discoveryCache = &openid.SimpleDiscoveryCache{}I get no compile errors but it crashesI'm sure you'll look at my code and go what the hell (I'm fairly new and only have a week or so experience with Golang so please feel free to correct anything)Obviously I have done something wrong, I basically looked at the NonceStore.go and DiscoveryCache.go on the github for OpenId, replicated it, but replaced the map with database insert and select functionsIF anybody can point me in the right direction on how to implement this properly that would be much appreciated, thanks! If you need anymore information please ask. 解决方案 Ok. First off, I don't believe you that the code compiles.Let's look at some mistakes, shall we?db, err := sql.Open("mysql", "dbconnectinfo")This line opens a database connection. It should only be used once, preferably inside an init() function. For example,var db *sql.DBfunc 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) }}Bang. Now you're connected to your MySQL database.Now what?Well this (from Get) is gross: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)Instead, it should be this:// 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 &sdiUp next is this: /* 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 */If you've been paying attention, we can drop the first sql.Query line.Great, now we just have:rows, err := db.Query("SELECT ...")So, why don't you do what you did inside the Accept method and parse the rows using for rows.Next()... ? 这篇关于我如何实现我自己的OpenID接口,它使用MySQL数据库而不是内存存储的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 10-25 04:49