前言
因为大多数go集成第三方登录的示例都是前后端不分离,例如 goth,要改成前后端分离并不容易。
所以就自己简单实现了一个前后端分离的示例
实现
示例使用的gin
+ nextjs
的组合
具体实现
- 首先,需要到
Github
上去申请一个Oauth app
点击Setting
-> 滑到最下,选择Developer Settings
-> 选择Oauth apps
-> 点击New Oauth App
填写下面的内容
这里的3000端口是前端的端口,文章的最后提供了前端的示例代码
生成client secret
保存client id
和 client secret
2. 登录流程
后端代码示例
了解后原理后,写代码就容易了
示例代码中,为了简单,并没用数据库存储用户,将用户信息保存在全局变量中
需要的库
import (
"log"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/imroc/req/v3"
)
数据定义
type Token struct {
// success response
AccessToken string `json:"access_token,omitempty"`
TokenType string `json:"token_type,omitempty"`
Scope string `json:"scope,omitempty"`
// error response
Error string `json:"error,omitempty"`
ErrorDescription string `json:"error_description,omitempty"`
ErrorUri string `json:"error_uri,omitempty"`
}
type AuthUser struct {
Id string `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
AvatarUrl string `json:"avatar_url"`
}
type User struct {
// success response
Username string `json:"login,omitempty"`
Id int `json:"id,omitempty"`
AvatarUrl string `json:"avatar_url,omitempty"`
Email string `json:"email,omitempty"`
// error response
Message string `json:"message,omitempty"`
DocumentationUrl string `json:"documentation_url,omitempty"`
Status string `json:"status,omitempty"`
}
var globalUser AuthUser = AuthUser{}
main函数
func main() {
r := gin.Default()
// ... 接口代码 ...
log.Fatal(r.Run(":8000"))
}
用户登录接口
r.GET("/auth/github", func(c *gin.Context) {
code := c.Query("code")
// get access token
client := req.C()
token := Token{}
_, err := client.R().
SetQueryParams(map[string]string{
"client_id": "", // 替换成你的client_id
"client_secret": "", // 替换成你的client_secret
"code": code,
}).
SetHeader("Accept", "application/json").
SetSuccessResult(&token).
Post("https://github.com/login/oauth/access_token")
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if token.Error != "" || token.AccessToken == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": token.Error})
return
}
var user User{}
// get user info
_, err = client.R().
SetBearerAuthToken(token.AccessToken).
SetSuccessResult(&user).
Get("https://api.github.com/user")
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
globalUser.Id = strconv.Itoa(user.Id),
globalUser.Username: user.Username,
globalUser.Email: user.Email,
globalUser.AvatarUrl: user.AvatarUrl,
c.JSON(http.StatusOK, globalUser)
})
获取用户信息
r.GET("/user", func(c *gin.Context) {
c.JSON(http.StatusOK, au)
})
实现的效果
-
在登录界面中,点击使用github登录
-
进行授权,点击同意
-
之后跳转到用户界面,完成登录
总结
本文只是打通了登录流程,并没有实现用户认证功能。可以通过access_token
获取到用户的信息后,将用户信息保存在jwt_token
,将jwt_token
发送给前端,之后前端每次操作都带上jwt_token
进行验证,这部分的内容就留给大家自行实现
前端代码: https://github.com/cpf2021-gif/behu-web
最后
如果本文对你有帮助, 帮我点个赞👍(关注更好🥰