本篇文章主要介绍了 OAuth2.0 和 使用 Google 的 OAuth2.0 登录方式。

OAuth2.0 介绍

OAuth 2.0是OAuth协议的下一版本,但不向下兼容OAuth 1.0。OAuth 2.0关注客户端开发者的简易性,同时为Web应用、桌面应用、手机和智能设备提供专门的认证流程。

Facebook的新的Graph API只支持OAuth 2.0,Google在2011年3月也宣布Google API对OAuth 2.0的支持,Windows Live也支持OAuth 2.0。

在认证和授权的过程中涉及的三方包括: 1、服务提供方,用户使用服务提供方来存储受保护的资源,如照片,视频,联系人列表。 2、用户,存放在服务提供方的受保护的资源的拥有者。 3、客户端,要访问服务提供方资源的第三方应用,通常是网站,如提供照片打印服务的网站。在认证过程之前,客户端要向服务提供者申请客户端标识。

使用OAuth进行认证和授权的过程如下所示:

(A)用户打开客户端以后,客户端要求用户给予授权。 (B)用户同意给予客户端授权。 (C)客户端使用上一步获得的授权,向认证服务器申请令牌。 (D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。 (E)客户端使用令牌,向资源服务器申请获取资源。 (F)资源服务器确认令牌无误,同意向客户端开放资源

Google 的 OAuth2.0 登录方式

1 进入 Google Cloud Platform 创建一个项目

2 进入 API与服务界面,选择凭据管理,点击创建凭据,选择 OAuth 2.0 客户端 ID

3 应用类型为 web 应用,已获授权的 JavaScript 来源为 http://localhost:3000, 已获授权的重定向 URI 为 http://localhost:3000/GoogleCallback

4 记录下你的客户端 id 和客户端密钥,这些信息可以在 Google Cloud Platform 中找到

5 完整代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package main

import (
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"

	"golang.org/x/oauth2"
)

const htmlIndex = `<html><body>
<a href="/GoogleLogin">Log in with Google</a>
</body></html>
`

var endpotin = oauth2.Endpoint{
	AuthURL:  "https://accounts.google.com/o/oauth2/auth",
	TokenURL: "https://oauth2.googleapis.com/token",
}

var googleOauthConfig = &oauth2.Config{
	ClientID:     "287161932061-gr3l32h40p1uc82m3pd81n4ubju2qqia.apps.googleusercontent.com",
	ClientSecret: "GGOCSPX-H3g4W5sCWOl8V7KMXNRkywrXkJ1Y",
	RedirectURL:  "http://localhost:3000/GoogleCallback",
	Scopes: []string{"https://www.googleapis.com/auth/userinfo.profile",
		"https://www.googleapis.com/auth/userinfo.email",
		"https://www.googleapis.com/auth/analytics"},
	Endpoint: endpotin,
}

const oauthStateString = "random"

func main() {
	http.HandleFunc("/", handleMain)
	http.HandleFunc("/GoogleLogin", handleGoogleLogin)
	http.HandleFunc("/GoogleCallback", handleGoogleCallback)
	log.Println(http.ListenAndServe(":3000", nil))
}

func handleMain(w http.ResponseWriter, r *http.Request) {
	io.WriteString(w, htmlIndex)
}

func handleGoogleLogin(w http.ResponseWriter, r *http.Request) {
	url := googleOauthConfig.AuthCodeURL(oauthStateString)
	log.Println(url)
	http.Redirect(w, r, url, http.StatusTemporaryRedirect)
}

func handleGoogleCallback(w http.ResponseWriter, r *http.Request) {
	state := r.FormValue("state")
	if state != oauthStateString {
		log.Printf("invalid oauth state, expected '%s', got '%s'", oauthStateString, state)
		http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
		return
	}

	code := r.FormValue("code")
	log.Println(code)
	token, err := googleOauthConfig.Exchange(context.Background(), code)
	if err != nil {
		log.Printf("Code exchange failed with %v", err)
		http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
		return
	}
	log.Println(token)

	response, err := http.Get("https://www.googleapis.com/oauth2/v2/userinfo?access_token=" + token.AccessToken)

	defer response.Body.Close()
	contents, err := ioutil.ReadAll(response.Body)
	fmt.Fprintf(w, "Content: %s\n", contents)
}

6 运行代码,访问 localhost:3000,点击 Log in with Google,就会进入 Google 授权登陆界面。同意授权后,就会显示你的信息。

小结

本篇文章主要简单使用 OAuth2.0 进行Google 账户登陆。

参考