Gin框架Go实现Google OAuth2重定向时遭遇CORS错误求助
Gin框架Google OAuth2认证的CORS错误解决
问题场景
我使用Go语言的Gin框架搭建Web服务,实现Google OAuth2认证,新增了两个端点:
/google/sign-in:接收请求后重定向至谷歌授权页面/google/callback:用户选择有效谷歌账号后验证令牌并生成内部JWT
调用/google/sign-in时触发CORS错误,具体信息如下:
Access to XMLHttpRequest at 'https://accounts.google.com/o/oauth2/auth?access_type=online&client_id=xxxxxxxxxxxxx-337ka657nqlo84q6697vv2efsc2vqvm0.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fgoogle%2Fcallback&response_type=code&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&state=7e5f86fe352b4563c7d1bd62408285dcbc44e3e26a4f142bbae915279008ece6' (redirected from 'http://localhost:3000/google/sign-in') from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
我的代码
Gin路由配置
r := gin.Default() r.Use(cors.New(cors.Config{ AllowOrigins: []string{"*"}, AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"}, AllowHeaders: []string{"Origin", "Authorization", "Content-Type", "Content-Length", "Accept-Encoding", "X-CSRF-Token", "baggage", "sentry-trace", "X-User-Lang"}, })) r.POST("/google/sign-in", authController.RedirectToGoogleAuthPage) r.GET("/google/callback", authController.GoogleSignIn)
Auth控制器代码
func (a AuthController) RedirectToGoogleAuthPage(c *gin.Context) { googleAuthConfig := utils.GetGoogleAuthConfig() state := utils.GenerateRandomKey() url := googleAuthConfig.AuthCodeURL(state, oauth2.AccessTypeOnline) session := sessions.Default(c) session.Set(state, state) err := session.Save() if err != nil { c.JSON(http.StatusInternalServerError, a.Errors.InternalError(err.Error())) return } c.Header("X-Auth-State", state) c.Redirect(http.StatusTemporaryRedirect, url) }
注:googleAuthConfig已配置回调地址为http://localhost:3000/google/callback,且已添加至谷歌云OAuth凭据中。
解决方案
核心原因
你用AJAX请求POST接口触发重定向,但浏览器的AJAX请求受CORS规则限制,无法跨域跳转到第三方域名(谷歌账号页),且谷歌的响应不会携带Access-Control-Allow-Origin头,导致报错。
方案1:修改接口为GET,前端直接跳转
- 调整路由方法为GET:
// 把POST改成GET r.GET("/google/sign-in", authController.RedirectToGoogleAuthPage)
- 前端不要用AJAX请求,而是通过页面跳转访问该接口:
- 用HTML标签:
<a href="http://localhost:3000/google/sign-in">谷歌登录</a> - 或JS代码:
window.location.href = "http://localhost:3000/google/sign-in"
这种方式符合OAuth2的常规流程,浏览器页面跳转不受CORS限制。
方案2:后端返回授权URL,前端自行跳转
如果必须保留POST方法(比如需要传递额外参数),可以修改控制器代码,返回谷歌授权URL给前端,由前端主动跳转:
func (a AuthController) RedirectToGoogleAuthPage(c *gin.Context) { googleAuthConfig := utils.GetGoogleAuthConfig() state := utils.GenerateRandomKey() url := googleAuthConfig.AuthCodeURL(state, oauth2.AccessTypeOnline) session := sessions.Default(c) session.Set(state, state) err := session.Save() if err != nil { c.JSON(http.StatusInternalServerError, a.Errors.InternalError(err.Error())) return } // 返回授权URL和state,由前端跳转 c.JSON(http.StatusOK, gin.H{ "auth_url": url, "state": state, }) }
前端拿到auth_url后执行:window.location.href = auth_url,即可避开CORS问题。
内容的提问来源于stack exchange,提问作者carloberd
相关产品推荐
相关产品推荐

