How can I implement my own interface for OpenID th

2019-09-14 17:38发布

So I'm trying to use the OpenID package for Golang, located here: https://github.com/yohcop/openid-go

In 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 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

}

And my Noncestore.go package 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())
    }
}

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 crashes

I'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 functions

IF 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.

标签: mysql go openid
1条回答
ゆ 、 Hurt°
2楼-- · 2019-09-14 18:03

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.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)
    }
}

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 &sdi

Up 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()... ?

查看更多
登录 后发表回答