我使用go的oauth2包代表用户向Instagram发出请求。我要弄清楚的唯一部分是如何存储访问/刷新令牌,然后如何再次使用oauth2?这是我到目前为止的代码,它所做的就是获取访问令牌并向API发出一个请求。之后,我不知道该怎么做。
package main
import "net/http"
import "io/ioutil"
import "fmt"
import "html/template"
import "golang.org/x/oauth2"
var ClientID = YOUR_CLIENT_ID
var ClientSecret = YOUR_CLIENT_SECRET
var RedirectURI = "http://localhost:8080/redirect"
var authURL = "https://api.instagram.com/oauth/authorize"
var tokenURL = "https://api.instagram.com/oauth/access_token"
var templ = template.Must(template.New("index.html").ParseFiles("index.html"))
var igConf *oauth2.Config
func redirect(res http.ResponseWriter, req *http.Request) {
code := req.FormValue("code")
if len(code) != 0 {
tok, err := igConf.Exchange(oauth2.NoContext, code)
if err != nil {
fmt.Println(err)
http.NotFound(res, req)
return
}
if tok.Valid() {
client := igConf.Client(oauth2.NoContext, tok)
request, err := http.NewRequest("GET", "https://api.instagram.com/v1/users/self/?access_token="+tok.AccessToken, nil)
if err != nil {
fmt.Println(err)
http.NotFound(res, req)
return
}
resp, err := client.Do(request)
if err != nil {
fmt.Println(err)
http.NotFound(res, req)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(err)
http.NotFound(res, req)
return
}
res.Write(body)
}
http.NotFound(res, req)
}
}
func homePage(res http.ResponseWriter, req *http.Request) {
url := igConf.AuthCodeURL("", oauth2.AccessTypeOffline)
fmt.Println(url)
err := templ.Execute(res, url)
if err != nil {
fmt.Println(err)
}
}
func main() {
igConf = &oauth2.Config{
ClientID: ClientID,
ClientSecret: ClientSecret,
Endpoint: oauth2.Endpoint{
AuthURL: authURL,
TokenURL: tokenURL,
},
RedirectURL: RedirectURI,
Scopes: []string{"public_content", "comments"},
}
http.HandleFunc("/redirect", redirect)
http.HandleFunc("/", homePage)
http.ListenAndServe(":8080", nil)
}
答案 0 :(得分:3)
您可以将访问令牌存储在Cookie中,方法是在<p id="color"> </p>
函数的res.Write(body)
行之前插入以下代码:
redirect()
在其他一些处理程序中,你会再次读回这个令牌:
res.SetCookie(&Cookie{
Name: "access_token",
Value: tok.AccessToken,
Expires: time.Now().Add(time.Hour * 24), // expires in 24 hours
}
答案 1 :(得分:0)
为什么要存储访问令牌?
访问和刷新令牌都是承载令牌,应按照RFC 6750中的定义进行处理。
当他们回来并再次点击登录按钮时,您通常只需重新执行授权流程。
如果您存储令牌,则需要担心保护令牌中的数据,这些令牌可以访问有关您用户的一些相当特权的信息。
我建议您尽可能转到OpenID Connect以及使用JWT加密和签名的地方。
-Jim
答案 2 :(得分:0)
您好,我为令牌存储和管理编写了一个模块,该模块具有到期时间的延迟,请看一下该模块,我认为它可以帮助您, 我从中间件调用此存储来管理令牌
# storage.go
package token_store
import (
"sync"
"time"
)
type item struct {
token string
lastAccess int64
}
// storage structure to managing the store tokens
type Storage struct {
storeMap map[string]*item
lock sync.Mutex
}
func NewStore(len, expireTime int64) (s *Storage) {
// initial the storage
s = &Store{storeMap: make(map[string]*item, len)}
go func() {
// each minute check that token has expired or not
for now := range time.Tick(time.Minute) {
// lock the cache for updating the values
s.lock.Lock()
for key, value := range s.storeMap {
/*
if expiration time exceeded then start to removing
the token from cache
*/
if now.Unix()-value.lastAccess > expireTime {
delete(s.storeMap, key)
}
}
s.lock.Unlock()
}
}()
return
}
func (s *Storage) Len() int {
// return the len of storage map
return len(s.storeMap)
}
func (s *Storage) Put(key, value string) {
/*
value will be the authentication token
key can be user-name or anay things that you
want to access token within it
*/
s.lock.Lock()
if it, ok := s.storeMap[key]; !ok { // if token is not exist
it = &item{value, time.Now().Unix()}
s.storeMap[key] = it
} else { // if token exist then update the last access time
it.lastAccess = time.Now().Unix()
}
s.lock.Unlock()
}
func (s *Storage) Get(key string) (value string) {
/*
check out hte item
*/
s.lock.Lock()
if item, ok := s.storeMap[key]; ok { // check if item exist then pass the value
value = item.token
item.lastAccess = time.Now().Unix()
}
s.lock.Unlock()
return
}
我希望这篇文章对您有所帮助。