使用危险的安全方法在我的Reaction SharePoint现代Web部件中使用SetInnerHTML

Secure way to use dangerouslySetInnerHTML inside my react SharePoint Modern web part(使用危险的安全方法在我的Reaction SharePoint现代Web部件中使用SetInnerHTML)
本文介绍了使用危险的安全方法在我的Reaction SharePoint现代Web部件中使用SetInnerHTML的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试构建一个React.js SharePoint现代Web部件,它具有以下功能:-

  1. 在Web部件设置页>;>;内有两个名为"我们是谁"的域,用户可以在这两个域中输入我们的值。

  2. 该Web部件将呈现2个按钮&我们是谁&我们的价值;当用户单击任何按钮时,将显示一个弹出式窗口,其中包含在第1步中输入的HTML代码

如下:-

但是,为了能够在Web部件中以Rich-Text的形式呈现HTML代码,我必须在.tsx文件中使用dangerouslySetInnerHTML属性。如下:-

import * as React from 'react';
import { useId, useBoolean } from '@fluentui/react-hooks';
import {
  getTheme,
  mergeStyleSets,
  FontWeights,
  Modal,
  IIconProps,
  IStackProps,
} from '@fluentui/react';
import { IconButton, IButtonStyles } from '@fluentui/react/lib/Button';
export const MYModal2 = (myprops) => {
  const [isModalOpen, { setTrue: showModal, setFalse: hideModal }] = useBoolean(false);
  const [isPopup, setisPopup] = React.useState(true);
  const titleId = useId('title');
  React.useEffect(() => {
      showModal();
  }, [isPopup]);
  function ExitHandler() {
    hideModal();
    setisPopup(current => !current)
    myprops.handler();
  }

  return (
    <div>
      <Modal
        titleAriaId={titleId}
        isOpen={isModalOpen}
        onDismiss={ExitHandler}
        isBlocking={true}
        containerClassName={contentStyles.container}
      >
        <div className={contentStyles.header}>
          <span id={titleId}>Modal Popup</span>
          <IconButton
            styles={iconButtonStyles}
            iconProps={cancelIcon}
            ariaLabel="Close popup modal"
            onClick={ExitHandler}
          />
        </div>
        <div  className={contentStyles.body}>
        <p dangerouslySetInnerHTML={{__html:myprops.OurValue}}>
   </p>

        </div>
      </Modal>

    </div>

  );
};

const cancelIcon: IIconProps = { iconName: 'Cancel' };

const theme = getTheme();
const contentStyles = mergeStyleSets({
  container: {
    display: 'flex',
    flexFlow: 'column nowrap',
    alignItems: 'stretch',
  },
  header: [
    // eslint-disable-next-line deprecation/deprecation
    theme.fonts.xLarge,
    {
      flex: '1 1 auto',
      borderTop: '4px solid ${theme.palette.themePrimary}',
      color: theme.palette.neutralPrimary,
      display: 'flex',
      alignItems: 'center',
      fontWeight: FontWeights.semibold,
      padding: '12px 12px 14px 24px',
    },
  ],
  body: {
    flex: '4 4 auto',
    padding: '0 24px 24px 24px',
    overflowY: 'hidden',
    selectors: {
      p: { margin: '14px 0' },
      'p:first-child': { marginTop: 0 },
      'p:last-child': { marginBottom: 0 },
    },
  },
});
const stackProps: Partial<IStackProps> = {
  horizontal: true,
  tokens: { childrenGap: 40 },
  styles: { root: { marginBottom: 20 } },
};
const iconButtonStyles: Partial<IButtonStyles> = {
  root: {
    color: theme.palette.neutralPrimary,
    marginLeft: 'auto',
    marginTop: '4px',
    marginRight: '2px',
  },
  rootHovered: {
    color: theme.palette.neutralDark,
  },
};

为了确保dangerouslySetInnerHTML的安全,我执行了以下步骤:-

1-在My Node.js CMD&>>;中,我在项目目录中运行以下命令:-

npm install dompurify eslint-plugin-risxss

2-然后在我的上面.tsx我做了以下修改:-

  • 我添加了此导入import { sanitize } from 'dompurify';
  • 我将此不安全代码<p dangerouslySetInnerHTML={{__html:myprops.OurValue}}></p>替换为<div dangerouslySetInnerHTML={{ __html: sanitize(myprops.OurValue) }} />

所以我的问题是:-

  1. 我尝试保护dangerouslySetInnerHTML的方式正确吗?还是我错过了什么?

  2. 第二个问题,我如何测试sanitize()方法是否实际有效?

以下是我的完整Web部件代码:-

MyModalPopupWebPart.ts中:-

import * as React from 'react';
import * as ReactDom from 'react-dom';
import { Version } from '@microsoft/sp-core-library';
import {
  IPropertyPaneConfiguration,
  PropertyPaneTextField
} from '@microsoft/sp-property-pane';
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';

import * as strings from 'MyModalPopupWebPartStrings';
import MyModalPopup from './components/MyModalPopup';
import { IMyModalPopupProps } from './components/IMyModalPopupProps';

export interface IMyModalPopupWebPartProps {
  description: string;
  WhoWeAre: string;
  OurValue:string;
}

export default class MyModalPopupWebPart extends BaseClientSideWebPart<IMyModalPopupWebPartProps> {

  public render(): void {
    const element: React.ReactElement<IMyModalPopupProps> = React.createElement(
      MyModalPopup,
      {
        description: this.properties.description,
        WhoWeAre: this.properties.WhoWeAre,
        OurValue: this.properties.OurValue
      }
    );

    ReactDom.render(element, this.domElement);
  }

  protected onDispose(): void {
    ReactDom.unmountComponentAtNode(this.domElement);
  }

  protected get dataVersion(): Version {
    return Version.parse('1.0');
  }

  protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
    return {
      pages: [
        {
          header: {
            description: strings.PropertyPaneDescription
          },
          groups: [
            {
              groupName: strings.BasicGroupName,
              groupFields: [
                PropertyPaneTextField('WhoWeAre', {
                  label: "who We Are",
    multiline: true
                }),
                PropertyPaneTextField('OurValue', {
                  label: "Our value"
                }), PropertyPaneTextField('description', {
                  label: "Description",
    multiline: true
                }),
              ]
            }
          ]
        }
      ]
    };
  }
}

MyModalPopup.tsx:-

import * as React from 'react';
import { IMyModalPopupProps } from './IMyModalPopupProps';
import { DefaultButton } from '@fluentui/react/lib/Button';
import { MYModal } from './MYModal';
import { MYModal2 } from './MYModal2';

interface IPopupState {
  showModal: string;
}

export default class MyModalPopup extends React.Component<IMyModalPopupProps, IPopupState> {
  constructor(props: IMyModalPopupProps, state: IPopupState) {
    super(props);
    this.state = {
      showModal: ''
    };
    this.handler = this.handler.bind(this);
    this.Buttonclick = this.Buttonclick.bind(this);
  }
  handler() {
    this.setState({
      showModal: ''
    })
  }
  private Buttonclick(e, whichModal) {
    e.preventDefault();

    this.setState({ showModal: whichModal });
  }
  public render(): React.ReactElement<IMyModalPopupProps> {

    const { showModal } = this.state;

    return (
      <div>

        <DefaultButton onClick={(e) => this.Buttonclick(e, 'our-value')} text="Our Value" />
        { showModal === 'our-value' && <MYModal2 OurValue={this.props.OurValue} myprops={this.state} handler={this.handler} />}

        <DefaultButton onClick={(e) => this.Buttonclick(e, 'who-we-are')} text="Who We Are" />
        { showModal === 'who-we-are' && <MYModal WhoWeAre={this.props.WhoWeAre} myprops={this.state} handler={this.handler} />}
      </div>
    );
  }
}

推荐答案

实际上,您可以使用sanitize-html-react库来清理Html标记,并将清理后的结果呈现为dangerouslySetInnerHTML中的字符串:

以下是一个示例安全组件(使用JavaScript):

const defaultOptions = {
  allowedTags: [ 'a', 'div', 'span', ],
  allowedAttributes: {
    'a': [ 'href' ]
  },
  allowedIframeHostnames: ['www.example.com'],
  // and many extra configurations
};

const sanitize = (dirty, options) => ({
  __html: sanitizeHtml(
    dirty,
    options: { ...defaultOptions, ...options }
  )
});

const SanitizeHTML = ({ html, options }) => (
  <div dangerouslySetInnerHTML={sanitize(html, options)} />
);

在下面的示例中,SanitizeHTML组件将删除onclick,因为它不在您允许的配置中。

<SanitizeHTML html="<div><a href="youtube.com" onclick="alert('@')">link</a></div>" />

这篇关于使用危险的安全方法在我的Reaction SharePoint现代Web部件中使用SetInnerHTML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Update another component when Formik form changes(当Formik表单更改时更新另一个组件)
Formik validation isSubmitting / isValidating not getting set to true(Formik验证正在提交/isValiating未设置为True)
React Validation Max Range Using Formik(使用Formik的Reaction验证最大范围)
Validation using Yup to check string or number length(使用YUP检查字符串或数字长度的验证)
Updating initialValues prop on Formik Form does not update input value(更新Formik表单上的初始值属性不会更新输入值)
password validation with yup and formik(使用YUP和Formick进行密码验证)