zoukankan      html  css  js  c++  java
  • 转: CKEditor/CKFinder升级心得

    CKEditor/CKFinder升级心得

    这几天把一个旧项目中的fckeditor升级为ckeditor 3.2 + ckfinder 1.4.3 组合,下面是一些升级心得:

    一、CKFinder的若干问题

    1.单独使用
    ckfinder从原fckeditor分离出来以后可以单独使用,通常我习惯于在工具栏中添加ckfinder.dll,这样以后要使用ckfinder直接从工具箱拖出来即可.
     
    拖到页面中后,会形成这样一个控件实例:

    1
    <CKFinder:FileBrowser ID="FileBrowser1" runat="server"></CKFinder:FileBrowser>

    2.上传文件自动重命名
    修改ckfinder的源文件,找到Connector\CommandHandlers\FileUploadCommandHandler.cs这个文件,定位到:

    1
    2
    string sExtension = System.IO.Path.GetExtension( oFile.FileName );
    sExtension = sExtension.TrimStart( '.' );

    在下面加一行代码:

    1
    sFileName = DateTime.Now.ToString("yyyyMMddHHmmssfff") + "." + sExtension;

    即强制把文件名改为时间格式字符串.

    3.上传安全问题

    3.1 跟fckeditor类似,默认情况下ckfinder是不允许上传的,找到config.ascx这个文件,定位到

    1
    2
    3
    4
    public override bool CheckAuthentication()
    {
       return false;
    }

     在这里加入自己需要的判断逻辑,千万不要直接改成return true;这样相当于免费把自己的服务器变成一个网络硬盘+肉鸡,任何人都可以直接上传任何文件(包括木马),起码也得类似下面这样:

    1
    2
    3
    4
    public override bool CheckAuthentication()
    {
       return HttpContext.Current.User.Identity.IsAuthenticated;
    }

    如果您是用membership/role来认证的,上面代码要求用户登录后才能使用ckfinder的上传功能.

    3.2 文件扩展名校验

    默认情况下,ckfinder几乎能上传任何文件,所以设置允许上传的文件扩展名是必需的,ckfinder采用了黑白名单的做法,即同时可以设置"允许上传的扩展名"及"禁止上传的扩展名",config.ascx中可参考下面这样设置:

    1
    2
    3
    4
    5
    6
    7
    ResourceType type;
     
    type = ResourceType.Add("Zip");
    ...
    type.AllowedExtensions = new string[] { "zip" };
    type.DeniedExtensions = new string[] {"asp","aspx","jsp","php","ashx","js","html","htm" };
    ...

    这一段设置相当于只允许.zip文件上传,同时禁止.asp,.aspx...之类的服务端文件上传

    3.3 MIME类型/ContentType校验

    光有扩展名校验是远远不够的,比如在asp时代就有一种经典的攻击方式:

    a.先把asp木马文件扩展名改成.jpeg之类(这样就能绕过扩展名检验)
    b.然后利用其它发包工具(或直接用ckfinder的上传功能),上传"伪jpeg"文件
    c.如果网站还支持html代码的留言(或产品编码,个人简介编辑等),写上这样一行代码

    1
    <!--inlude file = "xxx.jpeg"-->

    这里xxx.jpeg即上传后的"伪jpeg"木马,如果服务端允许包含文件的话,浏览包含这行代码的页面,木马就能运行了!

    为了防止这类攻击,必须要在服务端做MIME/ContentType校验,因为文件的扩展名不管改成什么,其内在的MIME/ContentType是不会变的,修改方法:

    定位到Settings\ResourceType.cs,找到

    1
    2
    public string[] AllowedExtensions;
    public string[] DeniedExtensions;

    再增加二个数组

    1
    2
    public string[] AllowedMIMETypes;
    public string[] DeniedMIMETypes;

    相应的构造函数也加初始化代码:

    1
    2
    AllowedMIMETypes = new string[0];
    DeniedMIMETypes = new string[0];

    然后再增加一个方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    public bool CheckMIMEType(string mimeType)
    {
        mimeType = mimeType.Trim().ToLower();
     
        if (DeniedMIMETypes.Length > 0)
        {
        if (Array.IndexOf(this.DeniedMIMETypes, mimeType) >= 0)
        {
            return false;
        }
        }
     
        if (AllowedMIMETypes.Length > 0)
        {
        return (Array.IndexOf(this.AllowedMIMETypes, mimeType) >= 0);
        }
        else
        {
        return true;
        }
    }

    然后定位到Connector\CommandHandlers\FileUploadCommandHandler.cs,找到:

    1
    2
    3
    4
    if (!this.CurrentFolder.ResourceTypeInfo.CheckExtension(sExtension))
    {
        ConnectorException.Throw(Errors.InvalidExtension);
    }

    然后加上:

    1
    2
    3
    4
    5
    string sFileMIME = oFile.ContentType;
    if (!this.CurrentFolder.ResourceTypeInfo.CheckMIMEType(sFileMIME))//检测上传文件的MIME类型
    {
        ConnectorException.Throw(Errors.InvalidMIMEType);
    }

    最后再修改config.ascx,加上MIME类型的黑白名单:

    1
    2
    3
    4
    5
    6
    7
    8
    ResourceType type;
     
    type = ResourceType.Add("Zip");
    ...
    type.AllowedExtensions = new string[] { "zip" };
    type.DeniedExtensions = new string[] {"asp","aspx","jsp","php","ashx","js","html","htm" };
    type.AllowedMIMETypes = new string[] { "application/x-zip-compressed" };
    type.DeniedMIMETypes = new string[] {"text/plain" };

    这样就相对就安全一些了(当然服务器端还可以进一步做安全处理,不过这个话题再展开就变成"服务器安全设置"专题了,不在本文的讨论范围,暂不深入)

    4.上传文件大小限制

    默认情况下ResourceType的构造函数里,MaxSize=0即不对上传文件大小做限制,所以只要在config.ascx里加上限制就行了

    1
    2
    3
    type = ResourceType.Add("Zip");
    ...
    type.MaxSize = 0;

    即把这里的MaxSize改成想要的值即可(以字节为单位计算),注意:ResourceType 虽然有MaxSize成员,但其实上传代码中并未对上传文件大小做判断,而是在上传完成后生成缩略图时,才做了一次判断,如果需要在上传文件SaveAs 以前就做判断处理,自行加一条if语句,比较oFile.ContentLength与MaxSize即可

    5.上传后缩略图无法正常显示

    这是ckFinder在windows系统中的一个小bug,定位到Settings\Thumbnails.cs,找到public string GetTargetDirectory()方法,改成下面这样:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    if (Dir.Length == 0 || Dir.Substring(0,1)!="/") //如果Dir为空,或者只是相对路径
    {
        return HttpContext.Current.Server.MapPath(Url);
    }
    else
    {
        if (Dir.IndexOf(":\\") == -1)//如果不是物理路径
        {
            return HttpContext.Current.Server.MapPath(Dir);
        }
        else
        {
            return Dir;
        }
    }

    6.动态指定上传路径

    默认情况下无法用cs代码修改config.ascx中的BaseUrl设置,因为其后端代码ConfigFile中并没有提供修改BaseUrl的方法,这里我借用了fckeditor以前的用法:利用session来动态处理

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public string DynamicBaseUrl
    {           
        get
        {
        object _baseUrl = HttpContext.Current.Session["CKFinder:DynamicBaseUrl"];
        if (_baseUrl == null || string.IsNullOrEmpty(_baseUrl.ToString()))
        {
            _baseUrl = "/ckfinder/userfiles/";
        }
        this.BaseUrl = _baseUrl.ToString();
        return this.BaseUrl;
        }
    }

    如上,在Settings\ConfigFile.cs中增加一个属性,让其从session中取值,然后再把config.ascx中的BaseUrl改成下面这样

    1
    2
    //BaseUrl = "/ckfinder/userfiles/";
    BaseUrl = DynamicBaseUrl;

    最后在嵌入ckFinder的页面中类似这样处理:

    1
    2
    3
    4
    protected void Page_Load(object sender, EventArgs e)
    {
        Session["CKFinder:DynamicBaseUrl"] = "/upload/";
    }

    7.CKfinder免费版本如何去掉“那啥”的提示

    打开core\js\ckfinder_ie.js,找到 {en.call(window,qo);},改成{/*en.call(window,qo);*/}即可

    二、与CKeditor的整合

    1.CKeditor的设置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    window.onload = function () {
        CKEDITOR.replace("editor1", {
        filebrowserBrowseUrl: '/ckfinder/ckfinder.html', //启用浏览功能
        filebrowserImageBrowseUrl: '/ckfinder/ckfinder.html?Type=Image',
        filebrowserFlashBrowseUrl: '/ckfinder/ckfinder.html?Type=Flash',
        filebrowserUploadUrl: '/ckfinder/core/connector/aspx/connector.aspx?command=QuickUpload&type=Zip',
        filebrowserImageUploadUrl: '/ckfinder/core/connector/aspx/connector.aspx?command=QuickUpload&type=Image',
        filebrowserFlashUploadUrl: '/ckfinder/core/connector/aspx/connector.aspx?command=QuickUpload&type=Flash'
        });
    }

    这样就可以了,需要说明的"ckfinder.html?Type=Image"上的Type=XXX,即对应CKFinder中 Config.ascx的ResourceType设置,而且ResourceType的名称不能用中文名,否则在快速上传时无法上传到服务端。(很多地 方是在html中以js方式接收参数的,改成中文后会导致乱码,从而无法正确定位目录,熟悉js的朋友如果想让其支持中文Type名,技术上讲应该是可以 修改实现的)

    2.与Asp.Net默认安全性的冲突处理

    可参见上一篇博文,不再重复

    最后:CKFinder需要Session/ViewState,所以如果您的Asp.Net项目中禁用了Session或ViewState,可能会无法正常运行,解决办法要么启用Session/ViewState,要么自行修改CKFinder源代码

  • 相关阅读:
    微信小程序学习Course 9-2 云存储功能
    微信小程序学习Course 9-1 云数据库功能
    微信小程序学习Course 9 云开发功能
    微信小程序学习Course 6 界面交互API函数
    微信小程序学习Course 3-3 JS时间类型学习
    微信小程序案例TODO备忘录
    微信小程序学习Course 3-2 JS数组对象学习
    微信小程序学习Course 8 本地缓存API
    微信小程序学习Course 7 定时器功能
    常用excel函数语法及说明
  • 原文地址:https://www.cnblogs.com/Joans/p/2473506.html
Copyright © 2011-2022 走看看