OAuth弹出式跨网域安全React.js

我对如何使用弹出窗口(window.open)在React中实现OAuth感兴趣。

例如,我有:

  1. mysite.com-这是我打开弹出窗口的地方。
  2. passport.mysite.com/oauth/authorize-弹出窗口。

主要问题是如何在window.open(弹出窗口)和window.opener之间建立连接(众所周知,由于跨域安全性,window.opener为null,因此我们不能再使用它了。 )。

  

window.opener会在您导航到其他主机时(出于安全原因)被删除,因此无法解决。如果可能的话,唯一的选择应该是在框架内付款。顶层文档需要保留在同一主机上。

方案:

OAuth弹出式跨网域安全React.js

可能的解决方案:

  1. 使用here中所述的setInterval检查打开的窗口。
  2. 使用cross-storage(不值得恕我直言)。

那么2019年最好的推荐方法是什么?

  

React的包装器-https://github.com/Ramshackle-Jamathon/react-oauth-popup

jsj07123 回答:OAuth弹出式跨网域安全React.js

Khanh TO建议。带有localStorage的OAuth弹出窗口。基于react-oauth-popup

方案:

enter image description here

代码:

oauth-popup.tsx:

import React,{PureComponent,ReactChild} from 'react'

type Props = {
  width: number,height: number,url: string,title: string,onClose: () => any,onCode: (params: any) => any,children?: ReactChild,}

export default class OauthPopup extends PureComponent<Props> {

  static defaultProps = {
    onClose: () => {},width: 500,height: 500,url: "",title: ""
  };

  externalWindow: any;
  codeCheck: any;

  componentWillUnmount() {
    if (this.externalWindow) {
      this.externalWindow.close();
    }
  }

  createPopup = () => {
    const {url,title,width,height,onCode} = this.props;
    const left = window.screenX + (window.outerWidth - width) / 2;
    const top = window.screenY + (window.outerHeight - height) / 2.5;

    const windowFeatures = `toolbar=0,scrollbars=1,status=1,resizable=0,location=1,menuBar=0,width=${width},height=${height},top=${top},left=${left}`;

    this.externalWindow = window.open(
        url,windowFeatures
    );

    const storageListener = () => {
      try {
        if (localStorage.getItem('code')) {
          onCode(localStorage.getItem('code'));
          this.externalWindow.close();
          window.removeEventListener('storage',storageListener);
        }
      } catch (e) {
        window.removeEventListener('storage',storageListener);
      }
    }

    window.addEventListener('storage',storageListener);

    this.externalWindow.addEventListener('beforeunload',() => {
      this.props.onClose()
    },false);
  };

  render() {
    return (
      <div onClick={this.createPopup)}>
        {this.props.children}
      </div>
    );
  }
}

app.tsx

import React,{FC} from 'react'

const App: FC = () => {

  const onCode = async (): Promise<undefined> => {
    try {
      const res = await <your_fetch>
    } catch (e) {
      console.error(e);
    } finally {
      window.localStorage.removeItem('code'); //remove code from localStorage
    }
  }

  return (
    <OAuthPopup
      url={<your_url>}
      onCode={onCode}
      onClose={() => console.log('closed')}
      title="<your_title>">
      <button type="button">Enter</button>
    </OAuthPopup>
  );
};

export default App;
,

我曾经在window.open/window.opener bug on ms-edge的oauth登录流程中遇到问题

我在此问题之前的流向是

  • 在登录按钮上,单击打开弹出窗口
  • 成功登录后,oauth应用将重定向到我的域页面
  • 然后我使用弹出式窗口(window.opener.fn)中的oauth响应和父窗口中的数据从中调用父窗口的函数,然后关闭子弹出窗口

此问题发生后我的流量是

  • 在登录按钮上,单击打开弹出窗口
  • 创建一个setinterval以防万一(window.opener未定义)
  • 成功登录后,oauth应用将重定向到我的域页面
  • 检查window.opener是否可用,然后从上述流程中执行#3,并清除clearInterval
  • 如果window.opener不可用,则由于我在我的域页面上,因此我尝试设置localstorage,并尝试从父窗口的setInterval函数内部读取localstorage,然后清除localstorage和setInterval并继续。
  • (为了向后兼容)如果本地存储也不可用,则使用较短的到期时间(5-10秒)设置客户端cookie,并尝试在setInterval函数中读取cookie(document.cookie)父窗口并继续。
本文链接:https://www.f2er.com/3151432.html

大家都在问