示例程序演示如下内容:

  • 使用 goauth2 库从 Facebook 获取json类型的用户信息.

程序结构如下:

facebook-oauth2/app/
	models
		user.go   # 用户信息结构体
	controllers
		app.go    # 程序代码

浏览代码

OAuth2 概要

OAuth基于下面的配置处理授权请求:

var FACEBOOK = &oauth.Config{
	ClientId:     "95341411595",
	ClientSecret: "8eff1b488da7fe3426f9ecaf8de1ba54",
	AuthURL:      "https://graph.facebook.com/oauth/authorize",
	TokenURL:     "https://graph.facebook.com/oauth/access_token",
	RedirectURL:  "http://loisant.org:9000/Application/Auth",
}

处理过程如下:

  1. 程序将用户发送到 AuthURL.
  2. 用户同意授权
  3. Facebook 向用户发送重定向 URL, 并带回 code参数.
  4. 程序使用 codeTokenURL获取OAuth AccessToken
  5. 然后就可以使用AccessToken处理请求了.

代码

看看下面的代码:

func (c Application) Index() revel.Result {
	u := c.connected()
	me := map[string]interface{}{}
	if u != nil && u.AccessToken != "" {
		// 使用AccessToken获取用户信息
		...
	}

	authUrl := FACEBOOK.AuthCodeURL("foo")
	return c.Render(me, authUrl)
}

可以看到没有AccessToken,我们什么也做不了。 所以首先要生成一个授权链接。 (“foo” 是facebook带回重定向链接中的参数,现在还用不到它)

下面是个有趣的模板:

{{if .me}}
<h3>You're {{.me.name}} on Facebook</h3>
{{else}}
<a href="{{.authUrl}}">login</a>
{{end}}

如果用户已经登录,显示用户名字,否则引导用户到 Facebook 进行授权登录

如果用户接受了, 接下来Facebook 将授权信息带回 Auth:

func (c Application) Auth(code string) revel.Result {
	t := &oauth.Transport{Config: FACEBOOK}
	tok, err := t.Exchange(code)
	if err != nil {
		revel.ERROR.Println(err)
		return c.Redirect(Application.Index)
	}

	user := c.connected()
	user.AccessToken = tok.AccessToken
	return c.Redirect(Application.Index)
}

t.Exchange(code) 发送请求到 TokenURL 链接以获得AccessToken。如果成功,就保存用户信息,最后返回 Index:

func (c Application) Index() revel.Result {
	u := c.connected()
	me := map[string]interface{}{}
	if u != nil && u.AccessToken != "" {
		resp, _ := http.Get("https://graph.facebook.com/me?access_token=" +
			url.QueryEscape(u.AccessToken))
		defer resp.Body.Close()
		if err := json.NewDecoder(resp.Body).Decode(&me); err != nil {
			revel.ERROR.Println(err)
		}

现在有了AccessToken,我们生成一个请求来获取JSON结构用户信息,将其解码成一个map传递到模板。