- 取得連結
- X
- 以電子郵件傳送
- 其他應用程式
程式語言:Go
功能:運用 google 各種服務
google 官方 oauth2 範例
Go實戰--golang中OAuth2.0的使用(使用google賬號進行登陸驗證)
- Package:
- Google APIs
功能:運用 google 各種服務
申請 API Key
- 進入 Google APIs
- 上方:新增專案
- 資訊頁面:點選 啟用 API 和服務
- 憑證頁面:依需求建立憑證
基本用法
- 建立 client,內建已含認證方式,自定義 client 可在 Transport 實作
- service.New(client) 建立 service 呼叫 API
- service.apiService.apiCall(...) 建立 call
- call.parameter(...) 設定各種參數
- call.Do() 送出 request
- package main
- import (
- "fmt"
- "google.golang.org/api/drive/v3"
- )
- func main() {
- auth := NewAuth(redirectURL)
- client := auth.GetClient(clientsecretPath, "drive-go.json")
- service, err := drive.New(client)
- if err != nil {
- panic(err)
- }
- call := service.Files.List()
- call = call.PageSize(2)
- response, err := call.Do()
- if err != nil {
- panic(err)
- }
- }
oauth2 範例
- import (
- "encoding/json"
- "fmt"
- "io/ioutil"
- "log"
- "net"
- "net/http"
- "net/url"
- "os"
- "os/user"
- "path/filepath"
- "github.com/pkg/errors"
- "golang.org/x/net/context"
- "golang.org/x/oauth2"
- )
- // This variable indicates whether the script should launch a web server to
- // initiate the authorization flow or just display the URL in the terminal
- // window. Note the following instructions based on this setting:
- // * launchWebServer = true
- // 1. Use OAuth2 credentials for a web application
- // 2. Define authorized redirect URIs for the credential in the Google APIs
- // Console and set the RedirectURL property on the config object to one
- // of those redirect URIs. For example:
- // config.RedirectURL = "http://localhost:8090"
- // 3. In the startWebServer function below, update the URL in this line
- // to match the redirect URI you selected:
- // listener, err := net.Listen("tcp", "localhost:8090")
- // The redirect URI identifies the URI to which the user is sent after
- // completing the authorization flow. The listener then captures the
- // authorization code in the URL and passes it back to this script.
- // * launchWebServer = false
- // 1. Use OAuth2 credentials for an installed application. (When choosing
- // the application type for the OAuth2 client ID, select "Other".)
- // 2. Set the redirect URI to "urn:ietf:wg:oauth:2.0:oob", like this:
- // config.RedirectURL = "urn:ietf:wg:oauth:2.0:oob"
- // 3. When running the script, complete the auth flow. Then copy the
- // authorization code from the browser and enter it on the command line.
- const launchWebServer = true
- const missingClientSecretsMessage = `
- Please configure OAuth 2.0
- To make this sample run, you need to populate the client_secrets.json file
- found at:
- %v
- with information from the {{ Google Cloud Console }}{{ https://cloud.google.com/console }}For more information about the client_secrets.json file format, please visit:
- https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
- `
- // Auth for oauth2
- type Auth struct {
- redirectURL *url.URL
- config *oauth2.Config
- useTLS bool
- tlsCert, tlsKey string
- }
- // NewAuth create Auth
- func NewAuth(redirectURL string) *Auth {
- a := &Auth{}
- var err error
- a.redirectURL, err = url.Parse(redirectURL)
- if err != nil {
- log.Fatal(err)
- }
- return a
- }
- // SetTLS when redirectURL is TLS, it should be setted
- func (a *Auth) SetTLS(TLSCertPath, TLSKeyPath string) {
- a.tlsCert = TLSCertPath
- a.tlsKey = TLSKeyPath
- a.useTLS = true
- }
- // GetClient generate a Client. It returns the generated Client.
- // clientsecret file format reference to client_secret.json.sample
- func (a *Auth) GetClient(clientsecretPath, tokenFile string) *http.Client {
- ctx := context.Background()
- b, err := ioutil.ReadFile(clientsecretPath)
- if err != nil {
- log.Fatalf("Unable to read client secret file: %v", err)
- }
- // If modifying the scope, delete your previously saved credentials
- // at ~/.credentials/tokenFile
- err = a.configFromJSON(b)
- if err != nil {
- log.Fatalf("Unable to parse client secret file to config: %v", err)
- }
- // Use a redirect URI like this for a web app. The redirect URI must be a
- // valid one for your OAuth2 credentials.
- a.config.RedirectURL = a.redirectURL.String()
- // Use the following redirect URI if launchWebServer=false in oauth2.go
- // config.RedirectURL = "urn:ietf:wg:oauth:2.0:oob"
- cacheFile, err := a.tokenCacheFile(tokenFile)
- if err != nil {
- log.Fatalf("Unable to get path to cached credential file. %v", err)
- }
- token, err := a.tokenFromFile(cacheFile)
- if err != nil {
- if launchWebServer {
- fmt.Println("Trying to get token from web")
- token, err = a.getTokenFromWeb()
- } else {
- fmt.Println("Trying to get token from prompt")
- token, err = a.getTokenFromPrompt()
- }
- if err == nil {
- a.saveToken(cacheFile, token)
- }
- }
- return a.config.Client(ctx, token)
- }
- func (a *Auth) configFromJSON(jsonKey []byte, scope ...string) error {
- type cred struct {
- ClientID string `json:"client_id,omitempty"`
- ClientSecret string `json:"client_secret,omitempty"`
- RedirectURIs []string `json:"redirect_uris,omitempty"`
- AuthURI string `json:"auth_uri,omitempty"`
- TokenURI string `json:"token_uri,omitempty"`
- }
- var j struct {
- Web *cred `json:"web,omitempty"`
- Installed *cred `json:"installed,omitempty"`
- }
- if err := json.Unmarshal(jsonKey, &j); err != nil {
- return err
- }
- var c *cred
- switch {
- case j.Web != nil:
- c = j.Web
- case j.Installed != nil:
- c = j.Installed
- default:
- return fmt.Errorf("oauth2: no credentials found")
- }
- if len(c.RedirectURIs) < 1 {
- return errors.New("oauth2: missing redirect URL in the client_credentials.json")
- }
- a.config = &oauth2.Config{
- ClientID: c.ClientID,
- ClientSecret: c.ClientSecret,
- RedirectURL: c.RedirectURIs[0],
- Scopes: scope,
- Endpoint: oauth2.Endpoint{
- AuthURL: c.AuthURI,
- TokenURL: c.TokenURI,
- },
- }
- return nil
- }
- // startWebServer starts a web server that listens on http://localhost:8080.
- // The webserver waits for an oauth code in the three-legged auth flow.
- func (a *Auth) startWebServer() (codeCh chan string, err error) {
- listener, err := net.Listen("tcp", a.redirectURL.Host)
- if err != nil {
- return nil, errors.Wrapf(err, "net.Listen")
- }
- codeCh = make(chan string)
- handFunc := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- code := r.FormValue("code")
- codeCh <- code // send code to OAuth flow
- listener.Close()
- w.Header().Set("Content-Type", "text/plain")
- fmt.Fprintf(w, "Received code: %v\r\nYou can now safely close this browser window.", code)
- })
- if a.useTLS {
- log.Printf("create TLS Server\n")
- log.Printf("certPath: %s\n", a.tlsCert)
- log.Printf("keyPath: %s\n", a.tlsKey)
- go http.ServeTLS(listener, handFunc, a.tlsCert, a.tlsKey)
- } else {
- go http.Serve(listener, handFunc)
- }
- return codeCh, nil
- }
- // Exchange the authorization code for an access token
- func (a *Auth) exchangeToken(code string) (*oauth2.Token, error) {
- // set access_type offline for refresh token
- token, err := a.config.Exchange(oauth2.NoContext, code, oauth2.AccessTypeOffline)
- if err != nil {
- log.Fatalf("Unable to retrieve token %v", err)
- }
- return token, nil
- }
- // getTokenFromPrompt uses Config to request a Token and prompts the user
- // to enter the token on the command line. It returns the retrieved Token.
- func (a *Auth) getTokenFromPrompt() (*oauth2.Token, error) {
- authURL := a.config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
- var code string
- fmt.Printf("Go to the following link in your browser. After completing "+
- "the authorization flow, enter the authorization code on the command "+
- "line: \n%v\n", authURL)
- if _, err := fmt.Scan(&code); err != nil {
- log.Fatalf("Unable to read authorization code %v", err)
- }
- fmt.Println(authURL)
- return a.exchangeToken(code)
- }
- // getTokenFromWeb uses Config to request a Token.
- // It returns the retrieved Token.
- func (a *Auth) getTokenFromWeb() (*oauth2.Token, error) {
- codeCh, err := a.startWebServer()
- if err != nil {
- fmt.Printf("Unable to start a web server. %s", err)
- return nil, errors.Wrapf(err, "a.startWebServer")
- }
- authURL := a.config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
- err = openURL(authURL)
- if err != nil {
- log.Fatalf("Unable to open authorization URL in web server: %v", err)
- } else {
- fmt.Println("Your browser has been opened to an authorization URL.",
- "This program will resume once authorization has been provided.")
- fmt.Println(authURL)
- }
- // Wait for the web server to get the code.
- code := <-codeCh
- return a.exchangeToken(code)
- }
- // tokenCacheFile generates credential file path/filename.
- // It returns the generated credential path/filename.
- func (a *Auth) tokenCacheFile(fileName string) (string, error) {
- usr, err := user.Current()
- if err != nil {
- return "", err
- }
- tokenCacheDir := filepath.Join(usr.HomeDir, ".credentials")
- os.MkdirAll(tokenCacheDir, 0700)
- return filepath.Join(tokenCacheDir,
- url.QueryEscape(fileName)), err
- }
- // tokenFromFile retrieves a Token from a given file path.
- // It returns the retrieved Token and any read error encountered.
- func (a *Auth) tokenFromFile(file string) (*oauth2.Token, error) {
- f, err := os.Open(file)
- if err != nil {
- return nil, err
- }
- t := &oauth2.Token{}
- err = json.NewDecoder(f).Decode(t)
- defer f.Close()
- return t, err
- }
- // saveToken uses a file path to create a file and store the
- // token in it.
- func (a *Auth) saveToken(file string, token *oauth2.Token) {
- fmt.Println("trying to save token")
- fmt.Printf("Saving credential file to: %s\n", file)
- f, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
- if err != nil {
- log.Fatalf("Unable to cache oauth token: %v", err)
- }
- defer f.Close()
- json.NewEncoder(f).Encode(token)
- }
參考
取得 Google API Key(金鑰) 流程,啟用服務 + 瞭解配額限制google 官方 oauth2 範例
Go實戰--golang中OAuth2.0的使用(使用google賬號進行登陸驗證)
留言
張貼留言