Angular 8跳转外部URL获取token路由匹配错误如何解决?
问题根因
Angular内置的Router服务仅用于处理应用内部的路由跳转,不支持直接跳转外部域名的URL,你传入完整的HTTPS地址时,Angular会把它当成内部路由路径去匹配路由表,自然会报Cannot match any routes的错误。
直接调用GET请求失败的原因
授权登录类的接口默认受浏览器同源策略限制,授权服务端一般不会配置CORS允许前端业务域名直接跨域请求,所以直接调用HttpClient的GET方法会被浏览器拦截,无法拿到返回结果。
可行解决方案
以下两个方案都可以实现不打开新页面获取token的需求:
方案1:隐藏iframe静默授权
如果授权服务器支持静默登录(用户已在授权域名下留存登录态,无需手动输入账号密码),可以通过插入隐藏iframe加载授权地址,监听跳转回调解析token:
if (!this.session.token) { const authUrl = 'https://www.url-system.com.br//auth&redirect_uri=http://8000/api/res-token'; // 创建隐藏iframe const iframe = document.createElement('iframe'); iframe.style.display = 'none'; iframe.src = authUrl; // 监听iframe加载事件,解析回调地址的token const handleLoad = () => { try { // 仅当redirect_uri和前端应用同源时,可正常读取iframe地址 const callbackUrl = iframe.contentWindow.location.href; // 根据回调地址的参数规则解析token,示例为取query参数的token const token = new URL(callbackUrl).searchParams.get('token'); if (token) { this.session.token = token; document.body.removeChild(iframe); // 此处补充拿到token后的业务逻辑 } } catch (err) { // 跨域报错属于正常情况,说明还未跳转到同源的回调地址,无需处理 } }; iframe.addEventListener('load', handleLoad); document.body.appendChild(iframe); }
注意:该方案要求授权配置的redirect_uri必须和前端应用域名同源,否则无法读取iframe内的地址信息
方案2:后端代理中转
直接由后端服务代理转发授权请求,前端只需要调用自有后端的接口,由后端拿到token后返回给前端,完全规避跨域问题,实现成本更低:
// 前端调用自有后端的代理接口 this.http.get('/api/proxy-auth').subscribe(res => { this.session.token = res.token; // 后续业务逻辑 })
后端仅需要做一层请求转发,携带所需参数请求授权地址,拿到返回结果后透传给前端即可。
如果你的项目使用标准OAuth2授权流程,可以直接用Angular生态下的成熟OAuth封装库,内置了静默授权、token自动刷新等能力,无需手动实现上述逻辑。
内容的提问来源于stack exchange,提问作者Rodrigo
相关产品推荐
相关产品推荐

