增加OAuth支持

This commit is contained in:
白茶清欢 2022-01-17 00:56:01 +08:00
parent 1b603bfd93
commit 3a4f5332c9
2 changed files with 157 additions and 0 deletions

29
oauth/define.go Normal file
View File

@ -0,0 +1,29 @@
// Package oauth ...
//
// Description : oauth ...
//
// Author : go_developer@163.com<张德满>
//
// Date : 2022/01/17 12:20 AM
package oauth
// Config OAuth相关配置
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2022/1/17 12:20 AM
type Config struct {
ClientID string `json:"client_id"` // 授权的client id
ClientSecret string `json:"client_secret"` // 授权的client_secret
CallbackURL string `json:"callback_url"` // 授权后携带code回调的地址
Domain string `json:"domain"` // 服务器域名
AuthorizationPageURI string `json:"authorization_page_uri"` // 授权页面URI
GetAccessTokenURI string `json:"get_access_token_uri"` // 获取access token地址
ValidateAccessTokenURI string `json:"validate_access_token_uri"` // 验证access_token地址
AccessTokenKey string `json:"access_token_key"` // 验证access token时的key
UseAuthorization bool `json:"use_authorization"` // 是否使用header中的Authorization
FormatAccessTokenFunc FormatAccessTokenFunc `json:"format_access_token_func"` // 格式化token的函数
}
// FormatAccessTokenFunc 格式化token
type FormatAccessTokenFunc func(token string) string

128
oauth/oauth.go Normal file
View File

@ -0,0 +1,128 @@
// Package oauth ...
//
// Description : oauth ...
//
// Author : go_developer@163.com<张德满>
//
// Date : 2022/01/17 12:18 AM
package oauth
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"github.com/pkg/errors"
"github.com/ddliu/go-httpclient"
)
// NewOAuth 获取OAuth实例
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2022/1/17 12:19 AM
func NewOAuth(cfg Config) *OAuth {
return &OAuth{
cfg: cfg,
}
}
// OAuth 管理
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2022/1/17 12:19 AM
type OAuth struct {
cfg Config
}
// GetAuthorizationPageURL 获取授权页面的URL
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2022/1/17 12:33 AM
func (o *OAuth) GetAuthorizationPageURL(scope string, responseType string) string {
return fmt.Sprintf(
"%s%s?client_id=%s&redirect_uri=%s&scope=%s&response_type=%s",
o.cfg.Domain,
o.cfg.AuthorizationPageURI,
o.cfg.ClientID,
url.QueryEscape(o.cfg.CallbackURL),
scope,
responseType,
)
}
// ApplyAccessTokenByCode 通过code申请授权token
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2022/1/17 12:35 AM
func (o *OAuth) ApplyAccessTokenByCode(code string, receiver interface{}) error {
// OAuth 授权回调
parameter := map[string]string{
"code": code,
"client_id": o.cfg.ClientID,
"client_secret": o.cfg.ClientSecret,
"grant_type": "authorization_code",
}
client := httpclient.NewHttpClient()
client.WithHeader("Accept", "application/json")
resp, err := client.Post(o.cfg.Domain+o.cfg.GetAccessTokenURI+"?grant_type=authorization_code", parameter)
if nil != err {
return err
}
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("【%v】%v", resp.StatusCode, resp.Status)
}
body, err := io.ReadAll(resp.Body)
if nil != err {
return errors.New("读取响应体失败: " + err.Error())
}
decoder := json.NewDecoder(bytes.NewReader(body))
decoder.UseNumber()
return decoder.Decode(receiver)
}
// ValidateAccessToken 验证授权token
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2022/1/17 12:43 AM
func (o *OAuth) ValidateAccessToken(token string, receiver interface{}) error {
if nil != o.cfg.FormatAccessTokenFunc {
token = o.cfg.FormatAccessTokenFunc(token)
}
parameter := make(map[string]string)
client := httpclient.NewHttpClient()
client.WithHeader("Accept", "application/json")
if o.cfg.UseAuthorization {
client.WithHeader("Authorization", "token "+token)
} else {
parameter[o.cfg.AccessTokenKey] = token
}
resp, err := client.Get("https://git.zhangdeman.cn/api/v1/user?grant_type=authorization_code", parameter)
if nil != err {
return err
}
body, err := io.ReadAll(resp.Body)
if nil != err {
return errors.New("读取响应体失败 : " + err.Error())
}
decoder := json.NewDecoder(bytes.NewReader(body))
decoder.UseNumber()
return decoder.Decode(receiver)
}
// GetUserDetailByToken 根据 token 获取用户详情
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2022/1/17 12:55 AM
func (o *OAuth) GetUserDetailByToken(token string, receiver interface{}) error {
return o.ValidateAccessToken(token, receiver)
}