add google oauth
This commit is contained in:
@@ -36,8 +36,8 @@
|
|||||||
|
|
||||||
#### 登录
|
#### 登录
|
||||||
|
|
||||||
- 添加了`github`登录,需要在后台配置好就可以用了,具体可看后台OAuth配置
|
- 添加了`github`和`google`授权登录,需要在后台配置好就可以用了,具体可看后台OAuth配置
|
||||||
- 添加了web后台授权登录
|
- 添加了web后台授权登录,点击后直接登录后台就自动登录客户端了
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -66,7 +66,7 @@
|
|||||||

|

|
||||||
5. 可以直接打开webclient,方便使用
|
5. 可以直接打开webclient,方便使用
|
||||||

|

|
||||||
6. Oauth,暂时只支持了`Github`, 需要创建一个`OAuth App`,然后配置到后台
|
6. Oauth,暂时只支持了`Github`和`Google`, 需要创建一个`OAuth App`,然后配置到后台
|
||||||

|

|
||||||
- `github oauth app`在`Settings`->`Developer settings`->`OAuth Apps`->`New OAuth App`
|
- `github oauth app`在`Settings`->`Developer settings`->`OAuth Apps`->`New OAuth App`
|
||||||
中创建,地址 [https://github.com/settings/developers](https://github.com/settings/developers)
|
中创建,地址 [https://github.com/settings/developers](https://github.com/settings/developers)
|
||||||
|
|||||||
+2
-2
@@ -36,7 +36,7 @@ desktop software that provides self-hosted solutions.
|
|||||||
|
|
||||||
#### Login
|
#### Login
|
||||||
|
|
||||||
- Added `GitHub` login, which can be used after configuration in the admin panel. See the OAuth configuration section
|
- Added `GitHub` and `Google` login, which can be used after configuration in the admin panel. See the OAuth configuration section
|
||||||
for details.
|
for details.
|
||||||
- Added authorization login for the web admin panel.
|
- Added authorization login for the web admin panel.
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ installation are `admin` `admin`, please change the password immediately.***
|
|||||||

|

|
||||||
5. You can open the web client directly for convenience:
|
5. You can open the web client directly for convenience:
|
||||||

|

|
||||||
6. OAuth support: Currently, only `GitHub` is supported. You need to create an `OAuth App` and configure it in the admin
|
6. OAuth support: Currently, `GitHub` and `Google` is supported. You need to create an `OAuth App` and configure it in the admin
|
||||||
panel.
|
panel.
|
||||||

|

|
||||||
- Create a `GitHub OAuth App`
|
- Create a `GitHub OAuth App`
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@ rustdesk:
|
|||||||
key: "123456789"
|
key: "123456789"
|
||||||
logger:
|
logger:
|
||||||
path: "./runtime/log.txt"
|
path: "./runtime/log.txt"
|
||||||
level: "error" #trace,debug,info,warn,error,fatal
|
level: "warn" #trace,debug,info,warn,error,fatal
|
||||||
report-caller: true
|
report-caller: true
|
||||||
redis:
|
redis:
|
||||||
addr: "127.0.0.1:6379"
|
addr: "127.0.0.1:6379"
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 24 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 10 KiB |
@@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Oauth struct {
|
type Oauth struct {
|
||||||
@@ -161,9 +162,8 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
c.String(http.StatusOK, "绑定成功")
|
c.String(http.StatusOK, "绑定成功")
|
||||||
return
|
return
|
||||||
}
|
} else if ac == service.OauthActionTypeLogin {
|
||||||
//登录
|
//登录
|
||||||
if ac == service.OauthActionTypeLogin {
|
|
||||||
if v.UserId != 0 {
|
if v.UserId != 0 {
|
||||||
c.String(http.StatusInternalServerError, "授权已经成功")
|
c.String(http.StatusInternalServerError, "授权已经成功")
|
||||||
return
|
return
|
||||||
@@ -181,7 +181,7 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//自动注册
|
//自动注册
|
||||||
u = service.AllService.UserService.RegisterByGithub(userData.Login, int64(userData.Id))
|
u = service.AllService.UserService.RegisterByGithub(userData.Login, strconv.Itoa(userData.Id))
|
||||||
if u.Id == 0 {
|
if u.Id == 0 {
|
||||||
c.String(http.StatusInternalServerError, "注册失败")
|
c.String(http.StatusInternalServerError, "注册失败")
|
||||||
return
|
return
|
||||||
@@ -193,19 +193,76 @@ func (o *Oauth) OauthCallback(c *gin.Context) {
|
|||||||
c.String(http.StatusOK, "授权成功")
|
c.String(http.StatusOK, "授权成功")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//返回js
|
//返回js
|
||||||
c.Header("Content-Type", "text/html; charset=utf-8")
|
c.Header("Content-Type", "text/html; charset=utf-8")
|
||||||
c.String(http.StatusOK, "授权错误")
|
c.String(http.StatusOK, "授权错误")
|
||||||
//up := &apiResp.UserPayload{}
|
|
||||||
//c.JSON(http.StatusOK, apiResp.LoginRes{
|
|
||||||
// AccessToken: ut.Token,
|
|
||||||
// Type: "access_token",
|
|
||||||
// User: *up.FromUser(u),
|
|
||||||
//})
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ty == model.OauthTypeGoogle {
|
||||||
|
code := c.Query("code")
|
||||||
|
err, userData := service.AllService.OauthService.GoogleCallback(code)
|
||||||
|
if err != nil {
|
||||||
|
c.String(http.StatusInternalServerError, "授权失败:"+err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//将空格替换成_
|
||||||
|
googleName := strings.Replace(userData.Name, " ", "_", -1)
|
||||||
|
if ac == service.OauthActionTypeBind {
|
||||||
|
//fmt.Println("bind", ty, userData)
|
||||||
|
utr := service.AllService.OauthService.UserThirdInfo(ty, userData.Email)
|
||||||
|
if utr.UserId > 0 {
|
||||||
|
c.String(http.StatusInternalServerError, "已经绑定其他账号")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//绑定
|
||||||
|
u := service.AllService.UserService.InfoById(v.UserId)
|
||||||
|
if u == nil {
|
||||||
|
c.String(http.StatusInternalServerError, "用户不存在")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//绑定
|
||||||
|
err = service.AllService.OauthService.BindGoogleUser(userData.Email, googleName, v.UserId)
|
||||||
|
if err != nil {
|
||||||
|
c.String(http.StatusInternalServerError, "绑定失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.String(http.StatusOK, "绑定成功")
|
||||||
|
return
|
||||||
|
} else if ac == service.OauthActionTypeLogin {
|
||||||
|
if v.UserId != 0 {
|
||||||
|
c.String(http.StatusInternalServerError, "授权已经成功")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
u := service.AllService.UserService.InfoByGoogleEmail(userData.Email)
|
||||||
|
if u == nil {
|
||||||
|
oa := service.AllService.OauthService.InfoByOp(ty)
|
||||||
|
if !*oa.AutoRegister {
|
||||||
|
//c.String(http.StatusInternalServerError, "还未绑定用户,请先绑定")
|
||||||
|
|
||||||
|
v.ThirdName = googleName
|
||||||
|
v.ThirdOpenId = userData.Email
|
||||||
|
url := global.Config.Rustdesk.ApiServer + "/_admin/#/oauth/bind/" + cacheKey
|
||||||
|
c.Redirect(http.StatusFound, url)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//自动注册
|
||||||
|
u = service.AllService.UserService.RegisterByGoogle(googleName, userData.Email)
|
||||||
|
if u.Id == 0 {
|
||||||
|
c.String(http.StatusInternalServerError, "注册失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v.UserId = u.Id
|
||||||
|
service.AllService.OauthService.SetOauthCache(cacheKey, v, 0)
|
||||||
|
c.String(http.StatusOK, "授权成功")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.String(http.StatusInternalServerError, "授权配置错误,请联系管理员")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WebOauthLogin
|
// WebOauthLogin
|
||||||
|
|||||||
+50
-3
@@ -68,7 +68,15 @@ type GithubUserdata struct {
|
|||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
Url string `json:"url"`
|
Url string `json:"url"`
|
||||||
}
|
}
|
||||||
|
type GoogleUserdata struct {
|
||||||
|
Email string `json:"email"`
|
||||||
|
FamilyName string `json:"family_name"`
|
||||||
|
GivenName string `json:"given_name"`
|
||||||
|
Id string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Picture string `json:"picture"`
|
||||||
|
VerifiedEmail bool `json:"verified_email"`
|
||||||
|
}
|
||||||
type OauthCacheItem struct {
|
type OauthCacheItem struct {
|
||||||
UserId uint `json:"user_id"`
|
UserId uint `json:"user_id"`
|
||||||
Id string `json:"id"` //rustdesk的设备ID
|
Id string `json:"id"` //rustdesk的设备ID
|
||||||
@@ -187,7 +195,7 @@ func (os *OauthService) GithubCallback(code string) (error error, userData *Gith
|
|||||||
}(resp.Body)
|
}(resp.Body)
|
||||||
|
|
||||||
// 在这里处理 GitHub 用户信息
|
// 在这里处理 GitHub 用户信息
|
||||||
if err := json.NewDecoder(resp.Body).Decode(&userData); err != nil {
|
if err = json.NewDecoder(resp.Body).Decode(&userData); err != nil {
|
||||||
global.Logger.Warn("failed decoding user info: %s\n", err)
|
global.Logger.Warn("failed decoding user info: %s\n", err)
|
||||||
error = errors.New("解析user info失败")
|
error = errors.New("解析user info失败")
|
||||||
return
|
return
|
||||||
@@ -195,6 +203,37 @@ func (os *OauthService) GithubCallback(code string) (error error, userData *Gith
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (os *OauthService) GoogleCallback(code string) (error error, userData *GoogleUserdata) {
|
||||||
|
err, oauthConfig := os.GetOauthConfig(model.OauthTypeGoogle)
|
||||||
|
token, err := oauthConfig.Exchange(context.Background(), code)
|
||||||
|
if err != nil {
|
||||||
|
global.Logger.Warn(fmt.Printf("oauthConfig.Exchange() failed: %s\n", err))
|
||||||
|
error = errors.New("获取token失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 创建 HTTP 客户端,并将 access_token 添加到 Authorization 头中
|
||||||
|
client := oauthConfig.Client(context.Background(), token)
|
||||||
|
resp, err := client.Get("https://www.googleapis.com/oauth2/v2/userinfo")
|
||||||
|
if err != nil {
|
||||||
|
global.Logger.Warn("failed getting user info: %s\n", err)
|
||||||
|
error = errors.New("获取user info失败: " + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func(Body io.ReadCloser) {
|
||||||
|
err := Body.Close()
|
||||||
|
if err != nil {
|
||||||
|
global.Logger.Warn("failed closing response body: %s\n", err)
|
||||||
|
}
|
||||||
|
}(resp.Body)
|
||||||
|
|
||||||
|
if err = json.NewDecoder(resp.Body).Decode(&userData); err != nil {
|
||||||
|
global.Logger.Warn("failed decoding user info: %s\n", err)
|
||||||
|
error = errors.New("解析user info失败:" + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (os *OauthService) UserThirdInfo(op, openid string) *model.UserThird {
|
func (os *OauthService) UserThirdInfo(op, openid string) *model.UserThird {
|
||||||
ut := &model.UserThird{}
|
ut := &model.UserThird{}
|
||||||
global.DB.Where("open_id = ? and third_type = ?", openid, op).First(ut)
|
global.DB.Where("open_id = ? and third_type = ?", openid, op).First(ut)
|
||||||
@@ -202,14 +241,22 @@ func (os *OauthService) UserThirdInfo(op, openid string) *model.UserThird {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (os *OauthService) BindGithubUser(openid, username string, userId uint) error {
|
func (os *OauthService) BindGithubUser(openid, username string, userId uint) error {
|
||||||
|
return os.BindOauthUser(model.OauthTypeGithub, openid, username, userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (os *OauthService) BindGoogleUser(email, username string, userId uint) error {
|
||||||
|
return os.BindOauthUser(model.OauthTypeGoogle, email, username, userId)
|
||||||
|
}
|
||||||
|
func (os *OauthService) BindOauthUser(thirdType, openid, username string, userId uint) error {
|
||||||
utr := &model.UserThird{
|
utr := &model.UserThird{
|
||||||
OpenId: openid,
|
OpenId: openid,
|
||||||
ThirdType: model.OauthTypeGithub,
|
ThirdType: thirdType,
|
||||||
ThirdName: username,
|
ThirdName: username,
|
||||||
UserId: userId,
|
UserId: userId,
|
||||||
}
|
}
|
||||||
return global.DB.Create(utr).Error
|
return global.DB.Create(utr).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (os *OauthService) UnBindGithubUser(userid uint) error {
|
func (os *OauthService) UnBindGithubUser(userid uint) error {
|
||||||
return global.DB.Where("user_id = ? and third_type = ?", userid, model.OauthTypeGithub).Delete(&model.UserThird{}).Error
|
return global.DB.Where("user_id = ? and third_type = ?", userid, model.OauthTypeGithub).Delete(&model.UserThird{}).Error
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-6
@@ -175,7 +175,17 @@ func (us *UserService) RouteNames(u *model.User) []string {
|
|||||||
|
|
||||||
// InfoByGithubId 根据githubid取用户信息
|
// InfoByGithubId 根据githubid取用户信息
|
||||||
func (us *UserService) InfoByGithubId(githubId string) *model.User {
|
func (us *UserService) InfoByGithubId(githubId string) *model.User {
|
||||||
ut := AllService.OauthService.UserThirdInfo(model.OauthTypeGithub, githubId)
|
return us.InfoByOauthId(model.OauthTypeGithub, githubId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InfoByGoogleEmail 根据googleid取用户信息
|
||||||
|
func (us *UserService) InfoByGoogleEmail(email string) *model.User {
|
||||||
|
return us.InfoByOauthId(model.OauthTypeGithub, email)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InfoByOauthId 根据oauth取用户信息
|
||||||
|
func (us *UserService) InfoByOauthId(thirdType, uid string) *model.User {
|
||||||
|
ut := AllService.OauthService.UserThirdInfo(thirdType, uid)
|
||||||
if ut.Id == 0 {
|
if ut.Id == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -187,12 +197,22 @@ func (us *UserService) InfoByGithubId(githubId string) *model.User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RegisterByGithub 注册
|
// RegisterByGithub 注册
|
||||||
func (us *UserService) RegisterByGithub(githubName string, githubId int64) *model.User {
|
func (us *UserService) RegisterByGithub(githubName string, githubId string) *model.User {
|
||||||
|
return us.RegisterByOauth(model.OauthTypeGithub, githubName, githubId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterByGoogle 注册
|
||||||
|
func (us *UserService) RegisterByGoogle(name string, email string) *model.User {
|
||||||
|
return us.RegisterByOauth(model.OauthTypeGoogle, name, email)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterByOauth 注册
|
||||||
|
func (us *UserService) RegisterByOauth(thirdType, thirdName, uid string) *model.User {
|
||||||
tx := global.DB.Begin()
|
tx := global.DB.Begin()
|
||||||
ut := &model.UserThird{
|
ut := &model.UserThird{
|
||||||
OpenId: strconv.FormatInt(githubId, 10),
|
OpenId: uid,
|
||||||
ThirdName: githubName,
|
ThirdName: thirdName,
|
||||||
ThirdType: model.OauthTypeGithub,
|
ThirdType: thirdType,
|
||||||
}
|
}
|
||||||
//global.DB.Where("open_id = ?", githubId).First(ut)
|
//global.DB.Where("open_id = ?", githubId).First(ut)
|
||||||
//这种情况不应该出现,如果出现说明有bug
|
//这种情况不应该出现,如果出现说明有bug
|
||||||
@@ -203,7 +223,7 @@ func (us *UserService) RegisterByGithub(githubName string, githubId int64) *mode
|
|||||||
// return u
|
// return u
|
||||||
//}
|
//}
|
||||||
|
|
||||||
username := us.GenerateUsernameByOauth(githubName)
|
username := us.GenerateUsernameByOauth(thirdName)
|
||||||
u := &model.User{
|
u := &model.User{
|
||||||
Username: username,
|
Username: username,
|
||||||
GroupId: 1,
|
GroupId: 1,
|
||||||
|
|||||||
Reference in New Issue
Block a user