Harness插件权限与生态:越权漏洞与发现机制的双重困境
2026/9/8 19:47:06
“嘿,各位江湖好汉!本菜鸟今天要搞个大事——给我的CMS系统装个’Word内容一键粘贴’的核武级功能!毕竟导师催论文、学校发新闻都靠它了,再不升级怕是要被导师的’死亡凝视’盯出洞来…”
/tiny-mce/plugins/doc_magic/ ├─ dialog.html # 多功能操作面板(Vue2适配版) ├─ doc_magic.js # 核心插件逻辑(超简单,就200行) └─ style.css # 样式文件(兼容IE8+)// 注册TinyMCE插件(Vue2/React通用,复制就能用)tinymce.PluginManager.add('doc_magic',function(editor,url){// 创建万能按钮(用了阿里云同款绿,好看!)constbtn=editor.ui.registry.addButton('doc_magic',{icon:'document',tooltip:'文档神器(粘贴/导入)',onAction:()=>showMagicDialog(editor)// 点击触发弹窗});// 显示多功能弹窗(Vue2轻量适配,不影响现有系统)functionshowMagicDialog(editor){editor.windowManager.open({title:'文档导入神器(学长亲测)',width:900,height:650,body:{type:'tabpanel',tabs:[{title:'粘贴内容',items:[{type:'textarea',name:'pasteContent',label:'粘贴Word/公众号内容(Ctrl+V)',multiline:true,maxHeight:300},{type:'button',text:'提取内容(学长推荐)',onclick:()=>processPaste(editor)// 处理粘贴},{type:'htmlpanel',htmlId:'pastePreview'// 预览区域}]},{title:'导入文档',items:[{type:'filepicker',name:'fileUpload',label:'选文件(支持docx/xlsx/pptx/pdf)',onchange:(e)=>handleFileUpload(e,editor)// 处理上传},{type:'htmlpanel',htmlId:'filePreview'// 预览区域}]},{title:'公众号导入',items:[{type:'textbox',name:'wechatUrl',label:'公众号文章链接(例:https://mp.weixin.qq.com/...)',maxWidth:500},{type:'button',text:'抓取内容(学长实测可用)',onclick:()=>fetchWechatContent(editor)// 抓取公众号},{type:'htmlpanel',htmlId:'wechatPreview'// 预览区域}]}]},buttons:[{type:'cancel',text:'关闭(学长说别点这个)'}]});}// 处理粘贴内容(图片自动上传OSS,保留样式)asyncfunctionprocessPaste(editor){constcontent=tinymce.activeEditor.dom.get('pasteContent').value;// 调用后端API(ASP.NET WebForm写的,超简单)constres=awaitfetch('/api/doc/process-paste',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({content})});constdata=awaitres.json();tinymce.activeEditor.dom.get('pastePreview').innerHTML=data.content;// 显示预览}// 处理文件上传(自动上传图片到OSS)asyncfunctionhandleFileUpload(e,editor){constfile=e.target.files[0];constformData=newFormData();formData.append('file',file);// 调用后端上传接口(ASP.NET处理OSS上传)constres=awaitfetch('/api/doc/upload-file',{method:'POST',body:formData});constdata=awaitres.json();tinymce.activeEditor.dom.get('filePreview').innerHTML=data.content;// 显示预览}// 抓取公众号内容(自动下载图片)asyncfunctionfetchWechatContent(editor){consturl=tinymce.activeEditor.dom.get('wechatUrl').value;constres=awaitfetch('/api/doc/fetch-wechat',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({url})});constdata=awaitres.json();tinymce.activeEditor.dom.get('wechatPreview').innerHTML=data.content;// 显示预览}});文档神器(学长版) // 兼容老浏览器的DOM操作(学长加的,防止IE8崩) function getElementsByClassName(className) { return document.querySelectorAll('.' + className); }Install-Package Aliyun.OSS.SDK.NetCore -Version 3.15.1)usingSystem;usingSystem.IO;usingSystem.Text.RegularExpressions;usingAliyun.OSS;usingMicrosoft.Office.Interop.Word;// 需安装Office(学长用的是WPS替代方案)usingAspose.Words;// 开源库,需自行下载(学长用的是免费版)publicclassDocProcessor{// OSS配置(从Web.config读)privatestaticstringossEndpoint=ConfigurationManager.AppSettings["OSS_Endpoint"];privatestaticstringossAccessKey=ConfigurationManager.AppSettings["OSS_AccessKey"];privatestaticstringossSecret=ConfigurationManager.AppSettings["OSS_Secret"];privatestaticstringossBucket=ConfigurationManager.AppSettings["OSS_Bucket"];// 处理粘贴的Word内容(图片上传OSS,保留样式)publicstringProcessPastedWord(stringhtml){// 1. 清理Word垃圾标签(学长实测有效)stringcleanHtml=CleanWordTags(html);// 2. 提取并上传图片(二进制存储,非Base64)cleanHtml=UploadImages(cleanHtml);// 3. 转换Latex为MathML(调用MathJax免费API)cleanHtml=ConvertLatexToMathML(cleanHtml);returncleanHtml;}// 解析Word文档(.docx)publicstringParseWord(stringfilePath){// 学长用Aspose.Words(免费版)解析,比Office Interop更稳定Documentdoc=newDocument(filePath);StringBuilderhtml=newStringBuilder("");// 处理段落(保留字体/字号/颜色)foreach(Paragraphparaindoc.Paragraphs){html.Append("");foreach(Runruninpara.Runs){html.Append("");html.Append(run.Text);html.Append("");}html.Append("");}// 处理表格(保留形状组)foreach(Tabletableindoc.Tables){html.Append("");foreach(Rowrowintable.Rows){html.Append("");foreach(Cellcellinrow.Cells){html.Append("");}html.Append("");}html.Append("").Append(ParseCell(cell)).Append("");}html.Append("");returnhtml.ToString();}// 辅助方法:清理Word垃圾标签(学长调了3晚的bug!)privatestringCleanWordTags(stringhtml){returnRegex.Replace(html,@".*?","",RegexOptions.Singleline).Replace("class=""MsoNormal""","").Replace("]+src=""data:image/(png|jpg);base64,(.*?)""[^>]*>");foreach(Matchmatchinmatches){stringbase64=match.Groups[2].Value;byte[]bytes=Convert.FromBase64String(base64);stringtempPath=Path.GetTempFileName()+".png";File.WriteAllBytes(tempPath,bytes);// 上传到OSS(学长写的方法,超简单)stringossUrl=UploadToOSS(tempPath,"paste_img_"+DateTime.Now.Ticks+".png");html=html.Replace(match.Value,$"");File.Delete(tempPath);// 删除临时文件}returnhtml;}// 辅助方法:上传文件到OSS(学长封装的,超好用)privatestringUploadToOSS(stringfilePath,stringfileName){OssClientossClient=newOssClient(ossEndpoint,ossAccessKey,ossSecret);stringobjectKey=$"cms_docs/{fileName}";// 存储路径:cms_docs/文件名try{ossClient.PutObject(ossBucket,objectKey,newFileStream(filePath,FileMode.Open));return$"https://{ossBucket}.{ossEndpoint}/{objectKey}";}catch(Exceptionex){return$"上传失败:{ex.Message}";}}// 辅助方法:Latex转MathML(调用MathJax免费API)privatestringConvertLatexToMathML(stringhtml){returnRegex.Replace(html,@"\$(.*?)\$",match=>{stringlatex=match.Groups[1].Value;try{// 调用MathJax API(免费,实测可用)stringmathml=newWebClient().DownloadString($"https://mathjax.github.io/MathJax-demos-web/convert-latex-to-mathml/?latex={latex}");returnmathml.Contains("false;}doc_magic插件文件夹丢进TinyMCE的plugins目录(路径:tinymce/plugins/)tinymce.init.js)中添加按钮:tinymce.init({selector:'#editor',// 你的编辑器容器IDplugins:'doc_magic',// 添加插件toolbar:'doc_magic bold italic'// 工具栏显示按钮});Web.config中的OSS信息改成你自己的(阿里云控制台获取)发布→IIS、FTP等→选择服务器)加群223813913,解锁以下隐藏福利:
群友真实反馈:“上周推荐了个政府项目,提成拿了3k,够买台新笔记本了!”
结语:学长把压箱底的代码都掏出来了,99元预算绝对够!有问题随时在群里喊我,24小时在线~ 祝大家都能拿到心仪的offer,外包接到手软!
npm install jquery// 引入tinymce-vueimportEditorfrom'@tinymce/tinymce-vue'import{WordPaster}from'../../static/WordPaster/js/w'import{zyOffice}from'../../static/zyOffice/js/o'import{zyCapture}from'../../static/zyCapture/z'//添加导入excel工具栏按钮(function(){'use strict';varglobal=tinymce.util.Tools.resolve('tinymce.PluginManager');functionselectLocalImages(editor){WordPaster.getInstance().SetEditor(editor).importExcel()}varregister$1=function(editor){editor.ui.registry.addButton('excelimport',{text:'',tooltip:'导入Excel文档',onAction:function(){selectLocalImages(editor)}});editor.ui.registry.addMenuItem('excelimport',{text:'',tooltip:'导入Excel文档',onAction:function(){selectLocalImages(editor)}});};varButtons={register:register$1};functionPlugin(){global.add('excelimport',function(editor){Buttons.register(editor);});}Plugin();}());//添加word转图片工具栏按钮(function(){'use strict';varglobal=tinymce.util.Tools.resolve('tinymce.PluginManager');functionselectLocalImages(editor){WordPaster.getInstance().SetEditor(editor);WordPaster.getInstance().importWordToImg()}varregister$1=function(editor){editor.ui.registry.addButton('importwordtoimg',{text:'',tooltip:'Word转图片',onAction:function(){selectLocalImages(editor)}});editor.ui.registry.addMenuItem('importwordtoimg',{text:'',tooltip:'Word转图片',onAction:function(){selectLocalImages(editor)}});};varButtons={register:register$1};functionPlugin(){global.add('importwordtoimg',function(editor){Buttons.register(editor);});}Plugin();}());//添加粘贴网络图片工具栏按钮(function(){'use strict';varglobal=tinymce.util.Tools.resolve('tinymce.PluginManager');functionselectLocalImages(editor){WordPaster.getInstance().SetEditor(editor);WordPaster.getInstance().UploadNetImg()}varregister$1=function(editor){editor.ui.registry.addButton('netpaster',{text:'',tooltip:'网络图片一键上传',onAction:function(){selectLocalImages(editor)}});editor.ui.registry.addMenuItem('netpaster',{text:'',tooltip:'网络图片一键上传',onAction:function(){selectLocalImages(editor)}});};varButtons={register:register$1};functionPlugin(){global.add('netpaster',function(editor){Buttons.register(editor);});}Plugin();}());//添加导入PDF按钮(function(){'use strict';varglobal=tinymce.util.Tools.resolve('tinymce.PluginManager');functionselectLocalImages(editor){WordPaster.getInstance().SetEditor(editor);WordPaster.getInstance().ImportPDF()}varregister$1=function(editor){editor.ui.registry.addButton('pdfimport',{text:'',tooltip:'导入pdf文档',onAction:function(){selectLocalImages(editor)}});editor.ui.registry.addMenuItem('pdfimport',{text:'',tooltip:'导入pdf文档',onAction:function(){selectLocalImages(editor)}});};varButtons={register:register$1};functionPlugin(){global.add('pdfimport',function(editor){Buttons.register(editor);});}Plugin();}());//添加导入PPT按钮(function(){'use strict';varglobal=tinymce.util.Tools.resolve('tinymce.PluginManager');functionselectLocalImages(editor){WordPaster.getInstance().SetEditor(editor);WordPaster.getInstance().importPPT()}varregister$1=function(editor){editor.ui.registry.addButton('pptimport',{text:'',tooltip:'导入PowerPoint文档',onAction:function(){selectLocalImages(editor)}});editor.ui.registry.addMenuItem('pptimport',{text:'',tooltip:'导入PowerPoint文档',onAction:function(){selectLocalImages(editor)}});};varButtons={register:register$1};functionPlugin(){global.add('pptimport',function(editor){Buttons.register(editor);});}Plugin();}());//添加导入WORD按钮(function(){'use strict';varglobal=tinymce.util.Tools.resolve('tinymce.PluginManager');functionselectLocalImages(editor){WordPaster.getInstance().SetEditor(editor).importWord()}varregister$1=function(editor){editor.ui.registry.addButton('wordimport',{text:'',tooltip:'导入Word文档',onAction:function(){selectLocalImages(editor)}});editor.ui.registry.addMenuItem('wordimport',{text:'',tooltip:'导入Word文档',onAction:function(){selectLocalImages(editor)}});};varButtons={register:register$1};functionPlugin(){global.add('wordimport',function(editor){Buttons.register(editor);});}Plugin();}());//添加WORD粘贴按钮(function(){'use strict';varglobal=tinymce.util.Tools.resolve('tinymce.PluginManager');varico="http://localhost:8080/static/WordPaster/plugin/word.png"functionselectLocalImages(editor){WordPaster.getInstance().SetEditor(editor).PasteManual()}varregister$1=function(editor){editor.ui.registry.addButton('wordpaster',{text:'',tooltip:'Word一键粘贴',onAction:function(){selectLocalImages(editor)}});editor.ui.registry.addMenuItem('wordpaster',{text:'',tooltip:'Word一键粘贴',onAction:function(){selectLocalImages(editor)}});};varButtons={register:register$1};functionPlugin(){global.add('wordpaster',function(editor){Buttons.register(editor);});}Plugin();}());在线代码:
// 插件plugins:{type:[String,Array],// default: 'advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools importcss insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars'default:'autoresize code autolink autosave image imagetools paste preview table powertables'},点击查看在线代码
// 初始化WordPaster.getInstance({// 上传接口:http://www.ncmem.com/doc/view.aspx?id=d88b60a2b0204af1ba62fa66288203edPostUrl:'http://localhost:8891/upload.aspx',// 为图片地址增加域名:http://www.ncmem.com/doc/view.aspx?id=704cd302ebd346b486adf39cf4553936ImageUrl:'http://localhost:8891{url}',// 设置文件字段名称:http://www.ncmem.com/doc/view.aspx?id=c3ad06c2ae31454cb418ceb2b8da7c45FileFieldName:'file',// 提取图片地址:http://www.ncmem.com/doc/view.aspx?id=07e3f323d22d4571ad213441ab8530d1ImageMatch:''})在编辑器中增加功能按钮
一键粘贴Word内容,自动上传Word中的图片,保留文字样式。
一键导入Word文件,并将Word文件转换成图片上传到服务器中。
一键导入PDF文件,并将PDF转换成图片上传到服务器中。
一键导入PPT文件,并将PPT转换成图片上传到服务器中。
一键自动上传网络图片。
点击下载完整示例