golang gin框架实现oauth2
原创
©著作权归作者所有:来自51CTO博客作者一耳听世界的原创作品,请联系作者获取转载授权,否则将追究法律责任
golang gin框架实现oauth2
1.获取依赖包
go get github.com/gin-gonic/gin
go get gopkg.in/oauth2.v3
go get github.com/google/uuid
2.项目结构和源码
项目地址
3.主要文件说明
main.go
package main
import (
"github.com/gin-gonic/gin"
"logistics/demo"
"logistics/oauth2"
)
func main() {
g := gin.Default()
auth := g.Group("/auth")
{
auth.GET("/token", oauth2.TokenRequest)
auth.GET("/credentials",oauth2.Credentials)
}
de := g.Group("/demo")
{
de.GET("/message",demo.Message)
}
de1 := g.Group("/demo1")
{
var c *gin.Context
//权限认证中间件
de1.Use(oauth2.AuthValidate(c))
de1.GET("/message",demo.Message1)
}
g.Run(":9096")
}
ginOauth.go
package oauth2
import (
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"gopkg.in/oauth2.v3"
"gopkg.in/oauth2.v3/errors"
"gopkg.in/oauth2.v3/manage"
"gopkg.in/oauth2.v3/models"
"gopkg.in/oauth2.v3/server"
"gopkg.in/oauth2.v3/store"
"log"
"logistics/model"
"time"
)
var (
gServer *server.Server
gClient *store.ClientStore
gManage *manage.Manager
baseResponse *model.Base
credentialsResponse *model.Credentials
)
/**
统一token返回格式
*/
func SetExtensionFields(ti oauth2.TokenInfo) map[string]interface{}{
data := map[string]interface{}{
"code": 1,
"message": "success",
}
return data
}
func init() {
gManage = manage.NewDefaultManager()
gManage.MustTokenStorage(store.NewMemoryTokenStore())
gClient = store.NewClientStore()
gManage.MapClientStorage(gClient)
gServer = server.NewDefaultServer(gManage)
gServer.SetAllowGetAccessRequest(true)
gServer.SetClientInfoHandler(server.ClientFormHandler)
var cfg = &manage.Config{AccessTokenExp: time.Hour * 200, RefreshTokenExp: time.Hour * 24 * 300, IsGenerateRefresh: true}
gManage.SetAuthorizeCodeTokenCfg(cfg)
gManage.SetRefreshTokenCfg(manage.DefaultRefreshTokenCfg)
gManage.SetClientTokenCfg(cfg)
gServer.SetExtensionFieldsHandler(SetExtensionFields)
gServer.SetInternalErrorHandler(func(err error) (re *errors.Response) {
log.Println("Internal Error:", err.Error())
return
})
gServer.SetResponseErrorHandler(func(re *errors.Response) {
log.Println("Response Error:", re.Error.Error())
})
}
func TokenRequest(c *gin.Context){
gServer.HandleTokenRequest(c.Writer, c.Request)
}
func Credentials(c *gin.Context){
clientId := uuid.New().String()[:16]
clientSecret := uuid.New().String()[:16]
err := gClient.Set(clientId, &models.Client{
ID: clientId,
Secret: clientSecret,
Domain: "http://localhost:9094",
})
if err != nil {
baseResponse = &model.Base{}
baseResponse.Code = 1000
baseResponse.Message = err.Error()
c.JSON(500, baseResponse)
c.Abort()
}
credentialsResponse = &model.Credentials{}
credentialsResponse.Code = 1
credentialsResponse.Message = "success"
credentialsResponse.ClientId = clientId
credentialsResponse.ClientSecret = clientSecret
c.JSON(200, credentialsResponse)
}
/**
权限验证中间件
*/
func AuthValidate(c *gin.Context) gin.HandlerFunc{
return func(c *gin.Context) {
_, err := gServer.ValidationBearerToken(c.Request)
if err != nil {
baseResponse = &model.Base{}
baseResponse.Code = 1001
baseResponse.Message = err.Error()
c.JSON(401, baseResponse)
c.Abort()
return
}else{
c.Next()
}
}
}
base.go
package model
type Base struct {
Code int `json:"code"`
Message string `json:"message"`
}
credentials.go
package model
type Credentials struct {
Base
ClientId string `json:"clientId"`
ClientSecret string `json:"clientSecret"`
}
test.go
package demo
import "github.com/gin-gonic/gin"
func Message(c *gin.Context){
c.JSON(200, "I not need auth")
}
func Message1(c *gin.Context){
c.JSON(200, "I need auth")
}
4.说明
代码中的
clientId := uuid.New().String()[:16]
clientSecret := uuid.New().String()[:16]
可以修改成固定值方便测试
5.请求
首先获取Credentials http://localhost:9096/auth/credentials 返回结果
{
"code": 1,
"message": "success",
"clientId": "a02156b4-1a46-43",
"clientSecret": "98871767-3760-46"
}
然后再获取accessToken http://localhost:9096/auth/token?grant_type=client_credentials&client_id=a02156b4-1a46-431&client_secret=98871767-3760-46&scope=all 返回结果
{
"access_token": "DK0LDFEHPEA19DCBXN8-2W",
"code": 1,
"expires_in": 720000,
"message": "success",
"refresh_token": "YCLVAWSKWGIV___ZNJIGDQ",
"scope": "all",
"token_type": "Bearer"
}
原来是没有code和message,为了统一增加的。
请求接口 http://localhost:9096/demo/message 这个不需要授权可以访问 返回结果
请求接口 http://localhost:9096/demo1/message 不加授权返回
{
"code": 1001,
"message": "invalid access token"
}
增加授权返回