go goth封装第三方认证库示例详解


Posted in Golang onAugust 14, 2022

简介

当前很多网站直接采用第三方认证登录,例如支付宝/微信/ Github 等。goth封装了接入第三方认证的方法,并且内置实现了很多第三方认证的实现:

go goth封装第三方认证库示例详解

图中截取的只是goth支持的一部分,完整列表可在其GitHub 首页查看。

快速使用

本文代码使用 Go Modules。

创建目录并初始化:

$ mkdir goth && cd goth
$ go mod init github.com/darjun/go-daily-lib/goth

安装goth库:

$ go get -u github.com/markbates/goth

我们设计了两个页面,一个登录页面:

// login.tpl
<a href="/auth/github?provider=github" rel="external nofollow" >Login With GitHub</a>

点击登录链接会请求/auth/github?provider=github

一个主界面:

// home.tpl
<p><a href="/logout/github" rel="external nofollow" >logout</a></p>
<p>Name: {{.Name}} [{{.LastName}}, {{.FirstName}}]</p>
<p>Email: {{.Email}}</p>
<p>NickName: {{.NickName}}</p>
<p>Location: {{.Location}}</p>
<p>AvatarURL: {{.AvatarURL}} <img src="{{.AvatarURL}}"></p>
<p>Description: {{.Description}}</p>
<p>UserID: {{.UserID}}</p>
<p>AccessToken: {{.AccessToken}}</p>
<p>ExpiresAt: {{.ExpiresAt}}</p>
<p>RefreshToken: {{.RefreshToken}}</p>

显示用户的基本信息。

同样地,我们使用html/template标准模板库来加载和管理页面模板:

var (
  ptTemplate *template.Template
)
func init() {
  ptTemplate = template.Must(template.New("").ParseGlob("tpls/*.tpl"))
}

主页面处理如下:

func HomeHandler(w http.ResponseWriter, r *http.Request) {
  user, err := gothic.CompleteUserAuth(w, r)
  if err != nil {
    http.Redirect(w, r, "/login/github", http.StatusTemporaryRedirect)
    return
  }
  ptTemplate.ExecuteTemplate(w, "home.tpl", user)
}

如果用户登录了,gothic.CompleteUserAuth(w, r)会返回一个非空的User对象,该类型有如下字段:

type User struct {
  RawData           map[string]interface{}
  Provider          string
  Email             string
  Name              string
  FirstName         string
  LastName          string
  NickName          string
  Description       string
  UserID            string
  AvatarURL         string
  Location          string
  AccessToken       string
  AccessTokenSecret string
  RefreshToken      string
  ExpiresAt         time.Time
  IDToken           string
}

如果已登录,显示主界面信息。如果未登录,重定向到登录界面:

func LoginHandler(w http.ResponseWriter, r *http.Request) {
  ptTemplate.ExecuteTemplate(w, "login.tpl", nil)
}

点击登录,由AuthHandler处理请求:

func AuthHandler(w http.ResponseWriter, r *http.Request) {
  gothic.BeginAuthHandler(w, r)
}

调用gothic.BeginAuthHandler(w, r)开始跳转到 GitHub 的验证界面。GitHub 验证完成后,浏览器会重定向到/auth/github/callback处理:

func CallbackHandler(w http.ResponseWriter, r *http.Request) {
  user, err := gothic.CompleteUserAuth(w, r)
  if err != nil {
    fmt.Fprintln(w, err)
    return
  }
  ptTemplate.ExecuteTemplate(w, "home.tpl", user)
}

如果登录成功,在 CallbackHandler 中,我们可以调用gothic.CompleteUserAuth(w, r)取出User对象,然后显示主页面。最后是消息路由设置:

r := mux.NewRouter()
r.HandleFunc("/", HomeHandler)
r.HandleFunc("/login/github", LoginHandler)
r.HandleFunc("/logout/github", LogoutHandler)
r.HandleFunc("/auth/github", AuthHandler)
r.HandleFunc("/auth/github/callback", CallbackHandler)
log.Println("listening on localhost:8080")
log.Fatal(http.ListenAndServe(":8080", r))

goth为我们封装了 GitHub 的验证过程,但是我们需要在 GitHub 上新增一个 OAuth App,生成 Client ID 和 Client Secret。

首先,登录 GitHub 账号,在右侧头像下拉框选择 Settings:

go goth封装第三方认证库示例详解

选择左侧 Developer Settings:

go goth封装第三方认证库示例详解

左侧选择 OAuth App,右侧点击 New OAuth App:

go goth封装第三方认证库示例详解

输入信息,重点是Authorization callback URL,这是 GitHub 验证成功之后的回调:

go goth封装第三方认证库示例详解

生成 App 之后,Client ID 会自动生成,但是 Client Secret 需要再点击右侧的按钮Generate a new client token生成:

go goth封装第三方认证库示例详解

生成了 Client Secret:

go goth封装第三方认证库示例详解

想要在程序中使用 Github,首先要创建一个 GitHub 的 Provider,调用github子包的New()方法:

githubProvider := github.New(clientKey, clientSecret, "http://localhost:8080/auth/github/callback")

第一个参数为 Client ID,第二个参数为 Client Secret,这两个是由上面的 OAuth App 生成的,第三个参数为回调的链接,这个必须与 OAuth App 创建时设置的一样。

然后应用这个 Provider:

goth.UseProviders(githubProvider)

准备工作完成,长吁一口气。现在运行程序:

$ SECRET_KEY="secret" go run main.go

浏览器访问localhost:8080,由于没有登录,重定向到localhost:8080/login/github

go goth封装第三方认证库示例详解

点击Login with GitHub,会重定向到 GitHub 授权页面:

go goth封装第三方认证库示例详解

点击授权,成功之后用户信息会保存在 session
中。跳转到主页面,显示我的信息:

go goth封装第三方认证库示例详解

更换 store

goth底层使用上一篇文章中介绍的gorilla/sessions库来存储登录信息,而默认采用的是 cookie 作为存储。另外选项默认采用:

如果需要更改存储方式或选项,我们可以在程序启动前,设置gothic.Store字段。例如我们要更换为 redistore:

store, _ = redistore.NewRediStore(10, "tcp", ":6379", "", []byte("redis-key"))
key := ""
maxAge := 86400 * 30  // 30 days
isProd := false
store := sessions.NewCookieStore([]byte(key))
store.MaxAge(maxAge)
store.Options.Path = "/"
store.Options.HttpOnly = true
store.Options.Secure = isProd
gothic.Store = store

总结

大家如果发现好玩、好用的 Go 语言库,欢迎到 Go 每日一库 GitHub 上提交 issue?

参考

goth GitHub:https://github.com/markbates/goth

Go 每日一库 GitHub:https://github.com/darjun/go-daily-lib

以上就是go goth封装第三方认证库示例详解的详细内容,更多关于go goth第三方认证库的资料请关注三水点靠木其它相关文章!

Golang 相关文章推荐
win10下go mod配置方式
Apr 25 Golang
Golang 获取文件md5校验的方法以及效率对比
May 08 Golang
Golang标准库syscall详解(什么是系统调用)
May 25 Golang
Go语言应该什么情况使用指针
Jul 25 Golang
golang为什么要统一错误处理
Apr 03 Golang
victoriaMetrics库布隆过滤器初始化及使用详解
Apr 05 Golang
golang操作redis的客户端包有多个比如redigo、go-redis
Apr 14 Golang
Golang Elasticsearches 批量修改查询及发送MQ
Apr 19 Golang
Golang map映射的用法
Apr 22 Golang
GoFrame gredis缓存DoVar Conn连接对象 自动序列化GoFrame gredisDo/DoVar方法Conn连接对象自动序列化/反序列化总结
Jun 14 Golang
Python测试框架pytest核心库pluggy详解
Aug 05 Golang
Go中使用gjson来操作JSON数据的实现
Aug 14 Golang
基于Python实现西西成语接龙小助手
Aug 05 #Golang
Python测试框架pytest核心库pluggy详解
Aug 05 #Golang
Go结合Gin导出Mysql数据到Excel表格
Aug 05 #Golang
GO中sync包自由控制并发示例详解
Aug 05 #Golang
Go语言编译原理之源码调试
Aug 05 #Golang
Go语言编译原理之变量捕获
Aug 05 #Golang
在ubuntu下安装go开发环境的全过程
Aug 05 #Golang
You might like
PHP将XML转数组过程详解
2013/11/13 PHP
jQuery ajax在GBK编码下表单提交终极解决方案(非二次编码方法)
2010/10/20 Javascript
JS小游戏之仙剑翻牌源码详解
2014/09/25 Javascript
javascript限制用户只能输汉字中文的方法
2014/11/20 Javascript
js实现图片懒加载效果
2017/07/17 Javascript
史上最全JavaScript数组去重的十种方法(推荐)
2017/08/17 Javascript
Element-UI Table组件上添加列拖拽效果实现方法
2018/04/14 Javascript
打通前后端构建一个Vue+Express的开发环境
2018/07/17 Javascript
解决vue打包css文件中背景图片的路径问题
2018/09/03 Javascript
jQuery使用each遍历循环的方法
2018/09/19 jQuery
Vue实现一个无限加载列表功能
2018/11/13 Javascript
Vue仿微信app页面跳转动画效果
2019/08/21 Javascript
Vue之Mixins(混入)的使用方法
2019/09/24 Javascript
vue-router结合vuex实现用户权限控制功能
2019/11/14 Javascript
通过angular CDK实现页面元素拖放的步骤详解
2020/07/01 Javascript
vue实现PC端分辨率适配操作
2020/08/03 Javascript
详解Python的Django框架中的模版相关知识
2015/07/15 Python
Windows下Eclipse+PyDev配置Python+PyQt4开发环境
2016/05/17 Python
Python机器学习之决策树算法实例详解
2017/12/06 Python
python实现批量修改图片格式和尺寸
2018/06/07 Python
linux安装Python3.4.2的操作方法
2018/09/28 Python
python3+PyQt5 创建多线程网络应用-TCP客户端和TCP服务器实例
2019/06/17 Python
Python获取当前脚本文件夹(Script)的绝对路径方法代码
2019/08/27 Python
解决pymysql cursor.fetchall() 获取不到数据的问题
2020/05/15 Python
美国领先的水果篮送货公司和新鲜水果供应商:The Fruit Company
2018/02/13 全球购物
Java的类可以定义为Protected或者Private得吗
2015/09/25 面试题
家长会邀请书
2014/01/25 职场文书
自我鉴定总结
2014/03/24 职场文书
房屋买卖协议书
2014/04/10 职场文书
《秋游》教学反思
2014/04/24 职场文书
大学生社会实践评语
2014/04/25 职场文书
医疗器械售后服务承诺书
2014/05/21 职场文书
承德避暑山庄导游词
2015/02/03 职场文书
送给客户微信问候语!
2019/07/04 职场文书
Nginx+SpringBoot实现负载均衡的示例
2021/03/31 Servers
MySQL单表千万级数据处理的思路分享
2021/06/05 MySQL