go实现github第三方登录
github进行第三方登录的【官方文档](https://docs.github.com/en/developers/apps/building-oauth-apps)的每一步指导都很详尽,开发者只需要按照其文档进行操作就能实现第三方登录的功能。大体步骤如下
- 创建一个授权应用
点击创建应用进行创建,页面如下
- 授权应用程序,获取code
当用户在第三方网站(即作为开发者的你开发的网站的登录页面)进行登录的时候,用户点击使用github进行登录,此时你应该引导用户跳转到github的授权登录页面,用户在登录之后,会跳转到第一步骤里面所填写的redirect_uri参数所指向的地址 - 根据code获取token
用户授权后,github重定向到你所填写的回调地址时,会携带一个code参数,这个参数的有效期只有10分钟,将在第四步骤使用到 - 根据token获取用户信息
拿到code参数之后,可以使用code参数重新向github发起请求,来获取用户的资料信息
代码目录结构
java0904@weigongdeMacBook-Pro github % tree
.
├── github
├── html
│ ├── github.jpeg
│ └── githubLogin.html
└── main.go
代码实现 main.go
package main
import (
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
"io/ioutil"
"net/http"
)
type GitHubConfig struct {
ClientId string
ClientSecret string
RedirectUrl string
}
type TokenResponse struct {
AccessToken string `json:"access_token"`
Scope string `json:"scope"`
TokenType string `json:"token_type"`
}
var conf = GitHubConfig{
"xxxx",
"xxxxxxxxxxxx",
"http://localhost:8080/authorization",
}
func main() {
engine := gin.Default()
engine.LoadHTMLGlob("html/*")
engine.GET("/", func(c *gin.Context) {
c.HTML(200, "githubLogin.tmpl", conf)
})
engine.GET("authorization", func(c *gin.Context) {
code, _ := c.GetQuery("code")
if code != "" {
token, err := getToken(code)
if err != nil {
panic(err)
}
info, err := getUserInfo(token.AccessToken)
if err != nil {
panic(err)
}
fmt.Println(info)
c.String(200, info)
} else {
c.String(500, "nil")
}
})
engine.Run(":8080")
}
func getToken(code string) (*TokenResponse, error) {
var token TokenResponse
client := &http.Client{}
request, err := http.NewRequest("GET", fmt.Sprintf("https://github.com/login/oauth/access_token?client_id=%s&client_secret=%s&code=%s", conf.ClientId, conf.ClientSecret, code), nil)
if err != nil {
return nil, err
}
request.Header.Set("Accept", "application/json")
response, err := client.Do(request)
if err != nil {
return nil, err
}
defer response.Body.Close()
if err = json.NewDecoder(response.Body).Decode(&token); err != nil {
return nil, err
}
return &token, nil
}
func getUserInfo(token string) (string, error) {
url := "https://api.github.com/user"
client := &http.Client{}
request, _ := http.NewRequest("GET", url, nil)
request.Header.Add("Authorization", "token "+token)
request.Header.Add("Accept", "application/json")
resp1, err := client.Do(request)
if err != nil {
panic(err)
}
defer resp1.Body.Close()
all, err := ioutil.ReadAll(resp1.Body)
if err != nil {
panic(err)
}
return string(all), nil
}
代码githubLogin.tmpl
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Bootstrap 101 Template</title>
<style>
body {
background-size: cover;
font-size: 16px;
}
.form {
background: rgba(255, 255, 255, 0.2);
width: 400px;
margin: 100px auto;
}
#login_form {
display: block;
}
#register_form {
display: none;
}
.fa {
display: inline-block;
top: 27px;
left: 6px;
position: relative;
color: #ccc;
}
input[type="text"], input[type="password"] {
padding-left: 26px;
}
.checkbox {
padding-left: 21px;
}
</style>
<!-- Bootstrap -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- HTML5 shim 和 Respond.js 是为了让 IE8 支持 HTML5 元素和媒体查询(media queries)功能 -->
<!-- 警告:通过 file:// 协议(就是直接将 html 页面拖拽到浏览器中)访问页面时 Respond.js 不起作用 -->
<!--[if lt IE 9]>
<script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container">
<div class="form row">
<form class="form-horizontal col-sm-offset-3 col-md-offset-3" id="login_form">
<h3 class="form-title">Login to your account</h3>
<div class="col-sm-9 col-md-9">
<div class="form-group">
<i class="fa fa-user fa-lg"></i>
<input class="form-control required" type="text" placeholder="Username" name="username"
autofocus="autofocus" maxlength="20"/>
</div>
<div class="form-group">
<i class="fa fa-lock fa-lg"></i>
<input class="form-control required" type="password" placeholder="Password" name="password"
maxlength="8"/>
</div>
<div class="form-group">
<label class="checkbox">
<input type="checkbox" name="remember" value="1"/> Remember me
</label>
<hr/>
<a href="javascript:;" id="register_btn" class="">Create an account</a>
</div>
<div class="form-group">
<a class="btn btn-success" href="https://github.com/login/oauth/authorize?client_id={{.ClientId}}&redirect_uri={{.RedirectUrl}}"><img width="50px" height="20px" src="html/github.jpeg">GitHub登录</a>
<input type="submit" class="btn btn-success pull-right" value="Login "/>
</div>
</div>
</form>
</div>
<div class="form row">
<form class="form-horizontal col-sm-offset-3 col-md-offset-3" id="register_form">
<h3 class="form-title">Login to your account</h3>
<div class="col-sm-9 col-md-9">
<div class="form-group">
<i class="fa fa-user fa-lg"></i>
<input class="form-control required" type="text" placeholder="Username" name="username"
autofocus="autofocus"/>
</div>
<div class="form-group">
<i class="fa fa-lock fa-lg"></i>
<input class="form-control required" type="password" placeholder="Password" id="register_password"
name="password"/>
</div>
<div class="form-group">
<i class="fa fa-check fa-lg"></i>
<input class="form-control required" type="password" placeholder="Re-type Your Password"
name="rpassword"/>
</div>
<div class="form-group">
<i class="fa fa-envelope fa-lg"></i>
<input class="form-control eamil" type="text" placeholder="Email" name="email"/>
</div>
<div class="form-group">
<input type="submit" class="btn btn-success pull-right" value="Sign Up "/>
<input type="submit" class="btn btn-info pull-left" id="back_btn" value="Back"/>
</div>
</div>
</form>
</div>
</div>
<!--<div class="container">-->
<!-- <h1>使用第三方登录测试页面</h1>-->
<!-- <a href="https://github.com/login/oauth/authorize?client_id={{.ClientId}}&redirect_uri={{.RedirectUrl}}">使用GitHub登录</a>-->
<!--</div>-->
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
</body>
</html>

go实现qq登录
目录结构
java0904@weigongdeMacBook-Pro qq % tree
.
├── html
│ ├── bt_92X1201.png
│ └── qqLogin.tmpl
├── main.go
└── qq
代码 qqLogin.tmpl
<html>
<body>
<a href="https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id={{.AppId}}&redirect_uri={{.RedirectURI}}">
<img src="html/bt_92X1201.png">
</a>
</body>
</html>
图片bt_92X1201.png
代码 main.go
package main
import (
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
"io/ioutil"
"net/http"
)
type GitHubConfig struct {
ClientId string
ClientSecret string
RedirectUrl string
}
type TokenResponse struct {
AccessToken string `json:"access_token"`
Scope string `json:"scope"`
TokenType string `json:"token_type"`
}
var conf = GitHubConfig{
"86650239386200a77f85",
"7dd8bb75fce6d8acc787f47a3bec6a755235e64d",
"http://localhost:8080/authorization",
}
func main() {
engine := gin.Default()
engine.LoadHTMLGlob("html/*")
engine.Static("/html", "/Users/java0904/goProject/loginGithub/github/html")
engine.GET("/", func(c *gin.Context) {
c.HTML(200, "githubLogin.html", conf)
})
engine.GET("authorization", func(c *gin.Context) {
code, _ := c.GetQuery("code")
if code != "" {
token, err := getToken(code)
if err != nil {
panic(err)
}
info, err := getUserInfo(token.AccessToken)
if err != nil {
panic(err)
}
fmt.Println(info)
c.String(200, info)
} else {
c.String(500, "nil")
}
})
engine.Run(":8080")
}
func getToken(code string) (*TokenResponse, error) {
var token TokenResponse
client := &http.Client{}
request, err := http.NewRequest("GET", fmt.Sprintf("https://github.com/login/oauth/access_token?client_id=%s&client_secret=%s&code=%s", conf.ClientId, conf.ClientSecret, code), nil)
if err != nil {
return nil, err
}
request.Header.Set("Accept", "application/json")
response, err := client.Do(request)
if err != nil {
return nil, err
}
defer response.Body.Close()
if err = json.NewDecoder(response.Body).Decode(&token); err != nil {
return nil, err
}
return &token, nil
}
func getUserInfo(token string) (string, error) {
url := "https://api.github.com/user"
client := &http.Client{}
request, _ := http.NewRequest("GET", url, nil)
request.Header.Add("Authorization", "token "+token)
request.Header.Add("Accept", "application/json")
resp1, err := client.Do(request)
if err != nil {
panic(err)
}
defer resp1.Body.Close()
all, err := ioutil.ReadAll(resp1.Body)
if err != nil {
panic(err)
}
return string(all), nil
}