Como Implementar a Colagem Segura de Word em um Sistema de Gerenciamento de Conteúdo Usando UEditor

Implmeentação da Solução Técnica

Este guia aborda a integração do plugin UEditor em um sistema CMS para permitir a colagem segura de conteúdo do Word, com foco na prevenção de ataques como XSS e na preservação de estilos.

Configuração do Frontend (Vue.js com UEditor Modificado)

// Arquivo: ueditor.config.js
window.UEDITOR_CONFIG = {
  pasteFilterStyle: false, // Desativa filtragem padrão para manter estilos
  toolbars: [
    ['codigo-fonte', 'desfazer', 'refazer', 'imagem-word', 'colagem-simples',
     '|', 'colagem-word-customizada', 'anti-xss'] // Botões personalizados
  ]
};

// Registrar botão de colagem personalizada no UEditor
UE.registerUI('colagem-word-customizada', function(editor, nomeUI) {
  const botao = new UE.ui.Button({
    name: 'colagem-word-customizada',
    title: 'Colagem de Word com Estilo Preservado',
    cssRules: 'background-position: -726px -77px;',
    onclick: function() {
      editor.execCommand('colagemDeWordSegura');
    }
  });
  return botao;
}, 10);

// Registrar botão de filtragem XSS no frontend
UE.registerUI('anti-xss', function(editor) {
  return new UE.ui.Button({
    name: 'anti-xss',
    title: 'Modo de Segurança Ativado',
    onclick: () => {
      const conteudo = editor.getContent();
      const conteudoSeguro = conteudo.replace(/<script>.*?<\/script>/gi, '');
      editor.setContent(conteudoSeguro);
    }
  });
});

// Comando principal para colagem segura com suporte a backend
UE.commands['colagemDeWordSegura'] = {
  execCommand: function() {
    document.addEventListener('colar', async (evento) => {
      const itens = (evento.clipboardData || window.clipboardData).items;
      for (let item of itens) {
        if (item.type.includes('office')) {
          const arquivo = item.getAsFile();
          const dadosFormulario = new FormData();
          dadosFormulario.append('documento-word', arquivo);

          // Chamada ao backend para análise segura
          const resposta = await fetch('/api/analise-word-segura', {
            method: 'POST',
            body: dadosFormulario,
            headers: { 'X-Token-Anti-CSRF': 'token-seguro' }
          });
          const { htmlGerado, linksOss } = await resposta.json();

          // Substituir caminhos de imagens por URLs do OSS
          let htmlFinal = htmlGerado.replace(/src="temp\//g, `src="${linksOss.join(',')}"`);
          this.execCommand('inserirHtml', htmlFinal);
        }
      }
    });
  }
};

Implementação do Backend (ASP.NET com Segurança Reforçada)

// Arquivo: AnaliseWordSegura.ashx
public class AnaliseWordSegura : IHttpHandler {
    public void ProcessRequest(HttpContext contexto) {
        // Validação de arquivo para evitar vulnerabilidades
        if (contexto.Request.Files.Count == 0 || !contexto.Request.Files[0].FileName.EndsWith(".docx")) {
            contexto.Response.Write("{\"erro\":\"Arquivo inválido\"}");
            return;
        }

        var arquivo = contexto.Request.Files[0];
        using (var documento = new XWPFDocument(arquivo.InputStream)) {
            // Sanitização para prevenir XSS
            var htmlConstruido = new StringBuilder();
            foreach (var paragrafo in documento.Paragraphs) {
                var textoSanitizado = HttpUtility.HtmlEncode(paragrafo.Text);
                htmlConstruido.AppendFormat("<p style="\"{0}\"">{1}</p>", paragrafo.Style, textoSanitizado);
            }

            // Upload de imagens para OSS com nomes aleatórios
            var urlsOss = new List<string>();
            foreach (var imagem in documento.AllPictures) {
                var nomeSeguro = Guid.NewGuid() + Path.GetExtension(imagem.SuggestFileExtension());
                var urlImagem = ServicoOSS.Enviar(imagem.Content, "imagens-word/" + nomeSeguro);
                urlsOss.Add(urlImagem);
            }

            // Retorno em formato JSON
            contexto.Response.ContentType = "application/json";
            contexto.Response.Write(JsonConvert.SerializeObject(new {
                html = htmlConstruido.ToString(),
                urlsOss = urlsOss
            }));
        }
    }
}

// Classe utilitária para operações no OSS
public static class ServicoOSS {
    private static readonly string endpoint = "seu-endpoint-oss";
    private static readonly string chaveAcesso = "sua-chave-acesso";
    private static readonly string chaveSecreta = "sua-chave-secreta";

    public static string Enviar(byte[] dados, string caminho) {
        // Validação de caminho para evitar ataques de path traversal
        if (caminho.Contains("..") || caminho.Contains("//"))
            throw new ArgumentException("Caminho inválido");

        var cliente = new OssClient(endpoint, chaveAcesso, chaveSecreta);
        using (var fluxo = new MemoryStream(dados)) {
            var resultado = cliente.PutObject("seu-bucket", caminho, fluxo);
            return resultado.Uri.ToString();
        }
    }
}
</string>

Tags: UEditor Vue.js ASP.NET Segurança Web XSS

Publicado em 7-29 19:32