用Go搞定微信扫码登录:一个后端接口+一个回调,附完整可运行代码
极简Go实现微信扫码登录两个接口搞定全流程每次看到新项目要接入微信登录就头疼文档翻来覆去看不明白其实用Go实现微信扫码登录核心代码不超过200行。今天我们就用最粗暴的方式把微信OAuth2.0登录简化为两个接口一个生成二维码一个处理回调。跟着做10分钟让你的Go服务支持微信登录。1. 准备工作比你想的更简单很多教程把微信登录讲复杂了。实际上你只需要微信开放平台账号个人/企业均可通过审核的网站应用没通过审核的只能用测试号记下AppID和AppSecret这两串字符# 用这个命令快速验证你的AppID和AppSecret是否有效 curl https://api.weixin.qq.com/sns/oauth2/access_token?appid你的AppIDsecret你的AppSecretgrant_typeclient_credential如果返回invalid appid检查应用是否通过审核AppID/AppSecret是否复制完整服务器IP是否加入白名单2. 核心接口一动态生成登录二维码第一个接口要做三件事构造微信授权URL生成二维码图片处理可能的错误// 用Gin框架示例 func GenerateQRCode(c *gin.Context) { appID : 你的AppID redirectURI : url.QueryEscape(你的回调地址) // 重要必须URL编码 // 构造微信授权URL注意state参数防CSRF攻击 authURL : fmt.Sprintf( https://open.weixin.qq.com/connect/qrconnect?appid%sredirect_uri%sresponse_typecodescopesnsapi_loginstate%s#wechat_redirect, appID, redirectURI, generateRandomString(16), ) // 生成二维码使用github.com/skip2/go-qrcode库 qr, err : qrcode.New(authURL, qrcode.Medium) if err ! nil { c.JSON(500, gin.H{error: 生成二维码失败}) return } // 直接返回PNG图片 png, err : qr.PNG(256) if err ! nil { c.JSON(500, gin.H{error: 二维码编码失败}) return } c.Data(200, image/png, png) }关键细节redirect_uri必须和开放平台配置的一致state参数要随机生成防止CSRF攻击二维码尺寸建议256px兼容移动端扫描3. 核心接口二优雅处理微信回调当用户扫码授权后微信会回调你的接口并携带code参数。这个接口要完成func HandleCallback(c *gin.Context) { code : c.Query(code) if code { c.JSON(400, gin.H{error: 缺少授权码}) return } // 第一步用code换access_token tokenURL : fmt.Sprintf( https://api.weixin.qq.com/sns/oauth2/access_token?appid%ssecret%scode%sgrant_typeauthorization_code, 你的AppID, 你的AppSecret, code, ) resp, err : http.Get(tokenURL) if err ! nil { c.JSON(500, gin.H{error: 获取access_token失败}) return } defer resp.Body.Close() var tokenResult struct { AccessToken string json:access_token ExpiresIn int json:expires_in RefreshToken string json:refresh_token OpenID string json:openid } if err : json.NewDecoder(resp.Body).Decode(tokenResult); err ! nil { c.JSON(500, gin.H{error: 解析token响应失败}) return } // 第二步用access_token获取用户信息 userInfoURL : fmt.Sprintf( https://api.weixin.qq.com/sns/userinfo?access_token%sopenid%s, tokenResult.AccessToken, tokenResult.OpenID, ) userResp, err : http.Get(userInfoURL) if err ! nil { c.JSON(500, gin.H{error: 获取用户信息失败}) return } defer userResp.Body.Close() var userInfo struct { OpenID string json:openid Nickname string json:nickname HeadImgURL string json:headimgurl } if err : json.NewDecoder(userResp.Body).Decode(userInfo); err ! nil { c.JSON(500, gin.H{error: 解析用户信息失败}) return } // 第三步处理业务逻辑示例返回JWT token token, err : generateJWTToken(userInfo.OpenID, userInfo.Nickname) if err ! nil { c.JSON(500, gin.H{error: 生成令牌失败}) return } c.JSON(200, gin.H{ token: token, user: gin.H{ nickname: userInfo.Nickname, avatar: userInfo.HeadImgURL, }, }) }避坑指南常见错误解决方案invalid code检查code是否过期10分钟有效期40163 code been usedcode只能使用一次40029 invalid code检查AppSecret是否正确4. 安全加固你必须做的三件事State参数验证// 生成随机state func generateState() string { b : make([]byte, 16) rand.Read(b) return hex.EncodeToString(b) } // 验证state if c.Query(state) ! expectedState { c.JSON(400, gin.H{error: 非法请求}) return }HTTPS强制要求微信要求回调地址必须是HTTPS本地测试可用ngrok等工具令牌刷新机制// 用refresh_token获取新的access_token refreshURL : fmt.Sprintf( https://api.weixin.qq.com/sns/oauth2/refresh_token?appid%sgrant_typerefresh_tokenrefresh_token%s, appID, refreshToken, )5. 前端配合极简实现方案前端只需要两个页面展示二维码的页面img src/api/auth/wechat/qrcode idqrcode script // 每60秒刷新一次二维码 setInterval(() { document.getElementById(qrcode).src /api/auth/wechat/qrcode?t Date.now() }, 60000) /script处理跳转的页面URL示例https://你的域名/auth/wechat/callback?codeXXXstateXXX// 从URL解析code const params new URLSearchParams(window.location.search) const code params.get(code) if (code) { // 发送code到后端获取token fetch(/api/auth/wechat/callback?code code) .then(res res.json()) .then(data { localStorage.setItem(token, data.token) window.location.href /dashboard }) }整套流程下来后端不到200行代码前端不到50行代码。这就是Go的魅力——用最少的代码解决实际问题。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2493287.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!