ReactJS - 使用 iframe 静默更新令牌 [英] ReactJS - Silently renew token with iframe

查看:45
本文介绍了ReactJS - 使用 iframe 静默更新令牌的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试围绕身份验证流程,每 60 分钟在我的 React 应用程序中实现一个无声令牌更新,如下所示:

  1. 创建一些观察者函数,它检查过期时间访问令牌.如果令牌即将到期,则需要对其进行续订.
  2. 渲染一个 iframe 标签,src 应该和你的 URL 相同用于重定向到 Auth 服务器,有一个区别:将返回 URL 更改为静态文件,我们称其为 redirect.html.服务器应该知道用户从存储的 cookie 中调用了这个 URL,所以它应该只是简单地将您重定向到redirect.html 文件,现在有一个新的访问令牌.
  3. 在这个redirect.html 中编写一个简短的脚本,它取出来自 URL 的令牌,并使用本地存储中已有的令牌覆盖它.
  4. 销毁 iframe.


<块引用>

Spotify 页面:

在 Spotify 开发页面,我保存了我常用的重定向 URL,用于首次从授权 URL 服务器获取令牌时:

http://localhost

然后我也用 Spotify 为我的 iframe 添加一个新的重定向 URL:

http://localhost/redirect_html


<块引用>

应用

App.jsx

这是我用于静默更新的组件,到目前为止,我正在父组件的 localhost/test-silent-renew 上测试,如下所示:

 <路由精确路径='/test-silent-renew' render={() =>(<SilentTokenRenew/>)}/>


<块引用>

组件

这是实际的刷新组件:

SilentTokenRenew.jsx

import React, { Component } from 'react'类 SilentTokenRenew 扩展组件 {构造函数(道具){超级(道具)this.state = {更新:假,isAuthenticated: 假}this.currentAttempt = 0this.maxNumberOfAttempts = 20this.state.renderIframe = this.renderIframe.bind(this);this.state.handleOnLoad = this.handleOnLoad.bind(this);};shouldComponentUpdate(nextProps, nextState) {返回 this.state.renewing !== nextState.renewing}componentDidMount() {this.timeInterval = setInterval(this.handleCheckToken, 20000)}componentWillUnmount() {clearInterval(this.timeInterval)}willTokenExpire = () =>{const accessToken = localStorage.getItem('spotifyAuthToken');console.log('access_token', accessToken)常量到期时间 = 3600const token = { accessToken, expireTime }//{ accessToken, expireTime }const threshold = 300//300s = 令牌过期的 5 分钟阈值const hasToken = 令牌 &&令牌.accessTokenconst now = (Date.now()/1000) + 阈值控制台日志('现在',现在)返回 !hasToken ||(现在> token.expirationTime)}handleCheckToken = () =>{如果 (this.willTokenExpire()) {this.setState({ 更新: true })clearInterval(this.timeInterval)}}沉默更新 = () =>{返回新的承诺((解决,拒绝)=> {const checkRedirect = () =>{//这可以是 econst redirectUrl = localStorage.getItem('silent-redirect-url-key')console.log('重定向 URL', redirectUrl)如果 (!redirectUrl) {this.currentAttempt += 1如果(this.currentAttempt > this.maxNumberOfAttempts){拒绝({message: '在尝试最大次数后无提示更新失败.',短:'max_number_of_attempts_reached',})返回}setTimeout(() => checkRedirect(), 500)返回}//清理你的 localStorage 以备下次静默更新localStorage.removeItem('silent-redirect-url-key')///redirect.html#access_token=......////在这里放置更多的错误处理程序////静默更新按预期工作,让我们更新访问令牌const session = this.extractTokenFromUrl(redirectUrl)//编写一些函数来从 URL 中获取访问令牌////按照你提供的代码,这里是设置的时间////提取的访问令牌返回到您的 localStorage 下的一个键 Credentials.stateKeylocalStorage.setItem(Credentials.stateKey, JSON.stringify(session))解决(会话)}检查重定向()})}handleOnLoad = () =>{this.silentRenew().then(() => {this.setState({ 更新: false })this.currentAttempt = 0this.timeInterval = setInterval(this.handleCheckToken, 60000)//静默更新访问令牌.}).catch(错误=> {this.setState({ 更新: false })//处理错误})}生成随机字符串(长度){让文字 = '';常量可能 ='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';for (让 i = 0; i < 长度; i++) {text += possible.charAt(Math.floor(Math.random() * possible.length));}返回文本;}renderIframe = () =>{const state = this.generateRandomString(16);const url = 新 URL('https://accounts.spotify.com/authorize?response_type=token&client_id=my_id&scope=user-read-currently-playing%20user-read-private%20user-library-read%20user-read-email%20user-read-playback-state%20user-follow-read%20playlist-read-private%20playlist-modify-public%20playlist-modify-private&redirect_uri=http%3A%2F%2Flocalhost&state=rBZaR9s1gHchWEME')console.log('URL HREF', url.href)console.log(url.searchParams.get('redirect_uri'))url.searchParams.set(Credentials.stateKey, state)url.searchParams.set('redirect_uri', 'http://localhost/redirect.html')//redirect.html 文件位置url.searchParams.set('提示', '无')//window.location = url;返回 (<iframe样式={{ 宽度:0,高度:0,位置:'绝对',左侧:0,顶部:0,显示:'无',可见性:'隐藏'}}宽度={0}高度={0}标题=沉默令牌更新";src={url.href}onLoad={this.handleOnLoad}/>)}使成为() {const { 更新 } = this.state返回更新?this.renderIframe() : null}}导出默认 SilentTokenRenew;


<块引用>

HTML

这是我的 iframe 的代码:

 <头><title>OAuth - 重定向</title><身体><p>更新...</p><脚本>//获取由父级设置为唯一请求键的窗口名称//或者如果没有指定参数,我们有一个来自 iframe 的静默更新const requestKey = 'silent-redirect-url-key'//使用重定向的 url 更新相应条目,该 url 应在查询参数/哈希中包含访问令牌或失败原因window.localStorage.setItem(requestKey, window.location.href);window.close();


如果我执行以下操作,我可以看到:

url.searchParams.set('prompt', 'none')window.location = url;///<-------

新令牌在那里,在浏览器 URL 重定向处.

但我似乎无法让我的

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆