OAuth 弹窗跨域安全 React.js [英] OAuth popup cross-domain security React.js

查看:32
本文介绍了OAuth 弹窗跨域安全 React.js的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

例如我有:

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

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

<块引用>

window.opener 每当您导航到不同的主机时都会被删除(出于安全原因),没有办法绕过它.如果可能的话,唯一的选择应该是在一个框架内付款.顶部文档需要保留在同一主机上.

方案:

可能的解决方案:

  1. 使用

    代码:

    oauth-popup.tsx:

    import React, {PureComponent, ReactChild} from 'react'类型道具 = {宽度:数字,高度:数字,网址:字符串,标题:字符串,onClose: () =>任何,onCode: (params: any) =>任何,孩子?:ReactChild,}导出默认类 OauthPopup 扩展 PureComponent;{静态 defaultProps = {onClose: () =>{},宽度:500,身高:500,网址:",标题: ""};外部窗口:任何;代码检查:任何;组件WillUnmount() {如果(this.externalWindow){this.externalWindow.close();}}createPopup = () =>{常量 {url, 标题, 宽度, 高度, onCode} = this.props;const left = window.screenX + (window.outerWidth - width)/2;常量顶部 = window.screenY + (window.outerHeight - 高度)/2.5;const windowFeatures = `toolbar=0,scrollbars=1,status=1,resizable=0,location=1,menuBar=0,width=${width},height=${height},top=${top},left=${左}`;this.externalWindow = window.open(网址,标题,窗口特点);常量 storageListener = () =>{尝试 {if (localStorage.getItem('code')) {onCode(localStorage.getItem('code'));this.externalWindow.close();window.removeEventListener('storage', storageListener);}} 抓住 (e) {window.removeEventListener('storage', storageListener);}}window.addEventListener('storage', storageListener);this.externalWindow.addEventListener('beforeunload', () => {this.props.onClose()}, 错误的);};使成为() {返回 (<div onClick={this.createPopup)}>{this.props.children}</div>);}}

    app.tsx

    import React, {FC} from 'react'const onCode = async (): Promise<undefined>=>{尝试 {const res = await <your_fetch>} 抓住 (e) {控制台.错误(e);} 最后 {window.localStorage.removeItem('code');//从localStorage中删除代码}}const App: FC = () =>;(

    I'm interested in how to implement OAuth in React using popup (window.open).

    For example I have:

    1. mysite.com — this is where I open the popup.
    2. passport.mysite.com/oauth/authorize — popup.

    The main question is how to create connection between window.open (popup) and window.opener (as it's known the window.opener is null due to cross-domain security therefore we can't use it anymore).

    window.opener is removed whenever you navigate to a different host (for security reasons), there is no way around it. The only option should be doing the payment in a frame if it is possible. The top document needs to stay on the same host.

    Scheme:

    Possible solutions:

    1. Check an opened window using setInterval described here.
    2. Using cross-storage (not worth it imho ).


    So what's the best recommended approach in 2019?

    Wrapper for React - https://github.com/Ramshackle-Jamathon/react-oauth-popup

    解决方案

    Suggested by Khanh TO. OAuth popup with localStorage. Based on react-oauth-popup.

    Scheme:

    Code:

    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,
            title,
            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 onCode = async (): Promise<undefined> => {
      try {
        const res = await <your_fetch>
      } catch (e) {
        console.error(e);
      } finally {
        window.localStorage.removeItem('code'); //remove code from localStorage
      }
    }
    
    const App: FC = () => (
      <OAuthPopup
        url={<your_url>}
        onCode={onCode}
        onClose={() => console.log('closed')}
        title="<your_title>">
        <button type="button">Enter</button>
      </OAuthPopup>
    );
    
    export default App;
    

    这篇关于OAuth 弹窗跨域安全 React.js的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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