package logic import ( "fmt" "fusenapi/utils/auth" "fusenapi/utils/basic" "log" "net/http" "time" "context" "fusenapi/server/auth/internal/svc" "fusenapi/server/auth/internal/types" "github.com/474420502/requests" "github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/rest/httpx" "golang.org/x/net/proxy" "golang.org/x/oauth2" "golang.org/x/oauth2/google" "gorm.io/gorm" ) type UserGoogleLoginLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext token string // 登录 token isRegistered bool // 是否注册 registerToken string // 注册邮箱的token oauthinfo *auth.OAuthInfo } func NewUserGoogleLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserGoogleLoginLogic { return &UserGoogleLoginLogic{ Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx, } } // 处理进入前逻辑w,r // func (l *UserGoogleLoginLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) { // } // 处理逻辑后 w,r 如:重定向, resp 必须重新处理 func (l *UserGoogleLoginLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) { if resp.Code == 200 { if !l.isRegistered { now := time.Now() rtoken, err := auth.GenerateRegisterToken( &l.svcCtx.Config.Auth.AccessSecret, l.svcCtx.Config.Auth.AccessExpire, now.Unix(), l.oauthinfo.Id, l.oauthinfo.Platform, ) if err != nil { resp.SetStatus(basic.CodeOAuthRegisterTokenErr) } l.registerToken = rtoken } rurl := fmt.Sprintf( l.svcCtx.Config.MainAddress+"/oauth?token=%s&is_registered=%t®ister_token=%s", l.token, l.isRegistered, l.registerToken, ) html := fmt.Sprintf(` Redirect `, rurl) fmt.Fprintln(w, html) } else { httpx.OkJson(w, resp) } } func (l *UserGoogleLoginLogic) UserGoogleLogin(req *types.RequestGoogleLogin, userinfo *auth.UserInfo) (resp *basic.Response) { // 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data) // userinfo 传入值时, 一定不为null dialer, err := proxy.SOCKS5("tcp", "127.0.0.1:1080", nil, proxy.Direct) if err != nil { log.Fatal(err) } customClient := &http.Client{ Transport: &http.Transport{ Dial: dialer.Dial, }, } ctx := context.WithValue(context.Background(), oauth2.HTTPClient, customClient) var googleOauthConfig = &oauth2.Config{ RedirectURL: "http://localhost:9900/api/user/oauth2/login/google", ClientID: l.svcCtx.Config.OAuth.Google.Appid, ClientSecret: l.svcCtx.Config.OAuth.Google.Secret, Scopes: []string{"https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile"}, Endpoint: google.Endpoint, } token, err := googleOauthConfig.Exchange(ctx, req.Code) if err != nil { logx.Error(err) resp.SetStatus(basic.CodeApiErr) } ses := requests.NewSession() ses.Config().SetProxy("socks5://127.0.0.1:1080") // 代理 为了测试功能 r, err := ses.Get("https://www.googleapis.com/oauth2/v2/userinfo?access_token=" + token.AccessToken).Execute() if err != nil { logx.Error(err) return resp.SetStatus(basic.CodeOAuthGoogleApiErr) } log.Println(r.Json()) googleId := r.Json().Get("id").Int() user, err := l.svcCtx.AllModels.FsUser.FindUserByGoogleId(context.TODO(), googleId) if err != nil { if err != gorm.ErrRecordNotFound { logx.Error(err) return resp.SetStatus(basic.CodeDbSqlErr) } // 进入邮件注册流程 if req.Email == "" { return resp.SetStatus(basic.CodeOK) } // 这里是注册模块, 发邮件, 通过邮件注册确认邮箱存在 // 邮箱验证格式错误 if !auth.ValidateEmail(req.Email) { return resp.SetStatus(basic.CodeOAuthEmailErr) } EmailManager.EmailTasks <- req.Email // email进入队 return resp.SetStatus(basic.CodeOK) } // 如果密码匹配,则生成 JWT Token。 nowSec := time.Now().Unix() jwtToken, err := auth.GenerateJwtToken(&l.svcCtx.Config.Auth.AccessSecret, l.svcCtx.Config.Auth.AccessExpire, nowSec, user.Id, 0) // 如果生成 JWT Token 失败,则抛出错误并返回未认证的状态码。 if err != nil { logx.Error(err) return resp.SetStatus(basic.CodeServiceErr) } l.token = jwtToken return resp.SetStatus(basic.CodeOK) }