这是我的stack:
1.前端服务器:Node + ReactJS(f.com
)
1.后端服务器(API):Golang(b.com
)
我在开发环境中使用create-react-app通过npm start
命令运行我的前端服务器。我想使用在sso.example.com/login
服务的SSO执行身份验证。理想情况下,每当有一个请求到后端服务器没有适当的授权,它将响应HTTP 302重定向到SSO页面。所以顺序是:
- ReactJS向
b.com/users
发送GET请求 - Golang回复了http.Redirect(“
sso.example.com/login
“) - ReactJS应用程序从
sso.example.com
获取CORS错误,其中我无法控制添加Access-Control-Allow-Origin:*
响应头
如何成功重定向GET请求?
4条答案
按热度按时间mhd8tkvw1#
在你的情况下,在客户端的浏览器中进行重定向会更容易,所以你不会有CORS问题(因为你是直接从SSO网站URL访问它)。
你可以用react来做,这很复杂:Programmatically navigate using react router V4
或者用
window
和普通的JavaScript来做,这很容易,但可能会导致浏览历史记录的问题:字符串
https://appendto.com/2016/04/javascript-redirect-how-to-redirect-a-web-page-with-javascript/的
x0fgdtte2#
React发送的
GET http://b.com/users
请求是XMLHttpRequest
还是fetch
请求?与导航请求不同,这些请求不会发生在浏览上下文中。(JavaScript程序可以在对这样的请求的响应中接收HTML页面,但是它不对该HTML做任何事情。)因此,这些请求不能用SSO登录流来认证,因为像SAML或OpenID Connect这样的SSO协议依赖于浏览上下文,浏览器会在浏览上下文中呈现带有响应的HTML页面。(如果用户还没有登录,他们必须在HTML页面中输入他们的凭据。)如果您的React应用依赖于对
b.com
的请求,那么您应该在应用开始向该网站发出任何请求之前 * 对该网站执行SSO登录流程。您可以显示一个按钮“登录b.com“,该按钮将在b.com
处打开一个弹出窗口。在此弹出窗口中,然后浏览器被重定向到sso.example.com/login
,(也许在用户给出他们的凭证之后)返回到b.com
。此时,用户登录到b.com
,可以再次关闭弹出窗口。(也有自动关闭这种登录弹出窗口的机制。)所有这些都将在React应用程序向
b.com
发出任何fetch
请求之前发生,并且由于它发生在浏览上下文中,因此根本不会涉及CORS。(See(Access to fetch at https://accounts.google.com/o/oauth2/v2/auth has been blocked by CORS)
r1wp621o3#
您有:
字符串
我认为CORS error的出现是因为SSO服务器(
sso.example.com
)没有在响应中包含必要的CORS头。由于您无法控制SSO服务器,因此需要在设置中实现一个解决方案。与其从Golang后端直接重定向到SSO服务器,不如在
b.com
上设置一个代理端点来处理重定向。该代理将在内部管理302重定向。当对
b.com/users
的请求缺乏适当的授权时,后端应该重定向到b.com
上的代理端点,而不是直接重定向到SSO服务器。然后,
b.com
上的代理端点可以执行到sso.example.com/login
的内部服务器端重定向。型
Golang后端将包括
型
对于代理服务器,您可以使用现有的反向代理工具或在Golang应用程序中编写自定义逻辑。代理将需要向
sso.example.com/login
执行HTTP请求并将响应中继回客户端。这样,您就可以避免CORS问题,因为重定向是在服务器端处理的,客户端不直接与
sso.example.com
交互。kx1ctssn4#
@paradite answer完全涵盖了你的问题,我想补充的是,在前端有React库为你处理这个问题:https://www.npmjs.com/package/@react-oauth/google或https://www.npmjs.com/package/react-social-login-buttons
它允许您使用一个预先制作的按钮,就像(在第一个包的情况下)
字符串
这真的取决于你的用例;在npm包网站上有几个例子,我最近在我的一个项目中使用了它,可以说它简化了过程。
在后端,您需要决定要使用哪种流:用途:登录(更简单)或授权(如果您需要额外的作用域、访问令牌、刷新令牌等)
第一个更简单,因为你得到了JWT,你解码和验证,你有用户信息。
如果你想实现后者,让你的后端从客户端获取
code
,然后你的后端必须与提供者交换它,类似于这样:型
令牌包括
access_token
、refresh_token
,您可以使用它们从提供程序获取用户信息。注意我在这里使用https://github.com/golang/oauth2库来实现协议。在你的处理程序中,你提取代码并调用这个函数,如果代码是有效的,你会得到userData,否则你会得到一个错误。
这绕过了CORS问题,并简化了解决方案。我在示例中使用了Google,但Oauth2库支持许多其他提供商。