// 跳转后的页面请求处理. // redirectURL?code=CODE&state=STATE // 授权 // redirectURL?state=STATE // 不授权 func RedirectURLHandler(w http.ResponseWriter, r *http.Request) { if err := r.ParseForm(); err != nil { // TODO: 处理 error return } state := r.FormValue("state") // TODO: 处理这个 state 参数, 判断是否是有效的 _ = state // NOTE: 实际开发中不要有这个 // 假定 state 有效 if code := r.FormValue("code"); code != "" { // 授权 client := oauth2.Client{ OAuth2Config: oauth2Config, } info, err := client.Exchange(code) if err != nil { // TODO: ... return } // TODO: 这里把 info 根据 info.OpenId 缓存起来,以后可以直接用 // 做相应的 session 处理。 _ = info // NOTE: 示例代码 } else { // 不授权 // TODO: 不授权的相应代码 } }
// 微信 oauth2 认证 // 需要提供 code, state 参数. func AuthHandler(ctx *gin.Context) { // MustAuthHandler(ctx) queryValues := ctx.Request.URL.Query() code := queryValues.Get("code") if code == "" { ctx.JSON(200, errors.ErrBadRequest) return } state := queryValues.Get("state") if state == "" { ctx.JSON(200, errors.ErrBadRequest) return } ss := ctx.MustGet("sso_session").(*session.Session) // 比较 state 是否一致 if !security.SecureCompareString(state, ss.OAuth2State) { ctx.JSON(200, errors.ErrOAuthStateMismatch) return } oauth2Client := oauth2.Client{ Config: oauth2Config, } oauth2Token, err := oauth2Client.Exchange(code) if err != nil { glog.Errorln(err) ctx.JSON(200, errors.ErrInternalServerError) return } if oauth2Token.UnionId == "" { glog.Errorln("unionid is empty") ctx.JSON(200, errors.ErrInternalServerError) return } timestamp := time.Now().Unix() user, err := model.GetByWechat(oauth2Token.UnionId) switch err { default: glog.Errorln(err) ctx.JSON(200, errors.ErrInternalServerError) return case model.ErrNotFound: var oauth2UserInfo openOAuth2.UserInfo if err = oauth2Client.GetUserInfo(&oauth2UserInfo, ""); err != nil { glog.Errorln(err) ctx.JSON(200, errors.ErrInternalServerError) return } user, err = model.AddByWechat(oauth2Token.UnionId, oauth2UserInfo.Nickname, timestamp) if err != nil { glog.Errorln(err) ctx.JSON(200, errors.ErrInternalServerError) return } fallthrough case nil: sid, err := session.NewSessionId() if err != nil { glog.Errorln(err) ctx.JSON(200, errors.ErrInternalServerError) return } tk2 := token.Token{ SessionId: sid, TokenId: token.NewTokenId(), AuthType: token.AuthTypeOAuthWechat, ExpirationAccess: token.ExpirationAccess(timestamp), ExpirationRefresh: token.ExpirationRefresh(timestamp), } tk2EncodedBytes, err := tk2.Encode() if err != nil { glog.Errorln(err) ctx.JSON(200, errors.ErrTokenEncodeFailed) return } ss2 := session.Session{ TokenSignature: tk2.Signatrue, UserId: user.Id, PasswordTag: user.PasswordTag, } if err = session.Add(sid, &ss2); err != nil { glog.Errorln(err) ctx.JSON(200, errors.ErrInternalServerError) return } resp := struct { *errors.Error Token string `json:"token"` }{ Error: errors.ErrOK, Token: string(tk2EncodedBytes), } ctx.JSON(200, &resp) return } }