• 开发笔记


    2016年9月  中秋前一天 岗位调整阔别了大爱已久的前端开发部,逐步进入后端开发阶段,不过还是偏前端方面的.

    2016.9.19 web前端与后端交互安全问题总结

      百度了很久感觉很不错的方式还是没有,也许可能是很多公司的秘密吧?噗~瞎猜的,大多数的意见还是先定IP,总感觉还是差点什么,这里用到的是服务器抓取提交参数IP并且根据客户端抓取到的提交设备信息(设备唯一编码,系统版本号,网络服务商等信息),组成一个设备唯一编码并和系统首次接受到对应用户提交IP地址作为默认绑定,每次提交的时候都会针对用户进行判断,当然这种方式并不是最好的方式,如果有web与后台交互安全性方面的大神希望多多指点!

    2016.9.22 IndexOf   Contains 字符查询 排序源码理解

      原作者:JunBird

    C#中字符串的比较操作

     

    字符串比较是比较常用的操作,一般出于以下两个原因比较字符串:

    • 判断相等
    • 字符串排序

    查询API判断字符串相等或排序时,由以下方法:

          public override bool Equals(object obj);
            public bool Equals(string value);
            public static bool Equals(string a, string b);
            public bool Equals(string value, StringComparison comparisonType);
            public static bool Equals(string a, string b, StringComparison comparisonType);
    
            public static int Compare(string strA, string strB);
            public static int Compare(string strA, string strB, bool ignoreCase);
            public static int Compare(string strA, string strB, StringComparison comparisonType);
            public static int Compare(string strA, string strB, bool ignoreCase, CultureInfo culture);
            public static int Compare(string strA, string strB, CultureInfo culture, CompareOptions options);
            public static int Compare(string strA, int indexA, string strB, int indexB, int length);
            public static int Compare(string strA, int indexA, string strB, int indexB, int length, bool ignoreCase);
            public static int Compare(string strA, int indexA, string strB, int indexB, int length, StringComparison comparisonType);
            public static int Compare(string strA, int indexA, string strB, int indexB, int length, bool ignoreCase, CultureInfo culture);
            public static int Compare(string strA, int indexA, string strB, int indexB, int length, CultureInfo culture, CompareOptions options);
    
            public static int CompareOrdinal(string strA, string strB);
            public static int CompareOrdinal(string strA, int indexA, string strB, int indexB, int length);
    
            public int CompareTo(object value);
            public int CompareTo(string strB);

    发现上述的方法中大多都有StringComparison类型的枚举,查询msdn后得到:

    stringComparison

    现简单写一段代码,测试Compare(string strA, string strB, StringComparison comparisonType)方法。分别用到StringComparison.CurrentCulture 和StringComparison.Ordinal。代码如下:

          static void Main(string[] args)
           {
               string strA = "asdfadsfasdfew我ò啊?地?方?的?asd";
               string strB = "adsfeaqfaead啊?多à发¢安2德?森-efadsfa";
               Stopwatch sw = new Stopwatch();
    
               sw.Start();
               for (int i = 0; i < 1000000; i++)
               {
                   string.Compare(strA, strB, StringComparison.CurrentCulture);
               }
               sw.Stop();
               Console.WriteLine(sw.ElapsedMilliseconds);
               
               sw.Reset();
               for (int i = 0; i < 1000000; i++)
               {
                   string.Compare(strA, strB,StringComparison.Ordinal);
               }
               sw.Stop();
               Console.WriteLine(sw.ElapsedMilliseconds);
    
               sw.Reset();
               for (int i = 0; i < 1000000; i++)
               {
                   string.CompareOrdinal(strA, strB);
               }
               sw.Stop();
               Console.WriteLine(sw.ElapsedMilliseconds);
           }

    执行结果如下:

    result

    测试结果非常明显,StringComparison.Currentculture显式传递了当前语言文化,而传递了String.Ordinal则会忽略指定的语言文化,这是执行字符串最快的一种方式。

    使用.NET Reflector查看源代码:

    public static int Compare(string strA, string strB, StringComparison comparisonType)
            {
                if ((comparisonType < StringComparison.CurrentCulture) || (comparisonType > StringComparison.OrdinalIgnoreCase))
                {
                    throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType");
                }
                if (strA == strB)
                {
                    return 0;
                }
                if (strA == null)
                {
                    return -1;
                }
                if (strB == null)
                {
                    return 1;
                }
                switch (comparisonType)
                {
                    case StringComparison.CurrentCulture:
                        return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, strB, CompareOptions.None);
    
                    case StringComparison.CurrentCultureIgnoreCase:
                        return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, strB, CompareOptions.IgnoreCase);
    
                    case StringComparison.InvariantCulture:
                        return CultureInfo.InvariantCulture.CompareInfo.Compare(strA, strB, CompareOptions.None);
    
                    case StringComparison.InvariantCultureIgnoreCase:
                        return CultureInfo.InvariantCulture.CompareInfo.Compare(strA, strB, CompareOptions.IgnoreCase);
    
                    case StringComparison.Ordinal:
                        return CompareOrdinalHelper(strA, strB);
    
                    case StringComparison.OrdinalIgnoreCase:
                        if (!strA.IsAscii() || !strB.IsAscii())
                        {
                            return TextInfo.CompareOrdinalIgnoreCase(strA, strB);
                        }
                        return CompareOrdinalIgnoreCaseHelper(strA, strB);
                }
                throw new NotSupportedException(Environment.GetResourceString("NotSupported_StringComparison"));
            }
    在上例中,同时测试了String的CompareOrdinal方法,效率同样惊人。查看其源代码后发现与Compare方法String.Ordinal源代码一样,此方法只是Compare方法的一个特例:
     
    public static int CompareOrdinal(string strA, string strB)
            {
                if (strA == strB)
                {
                    return 0;
                }
                if (strA == null)
                {
                    return -1;
                }
                if (strB == null)
                {
                    return 1;
                }
                return CompareOrdinalHelper(strA, strB);
            }

    接下来看看String.CompareTo()方法的源代码:

    [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
           public int CompareTo(string strB)
           {
               if (strB == null)
               {
                   return 1;
               }
               return CultureInfo.CurrentCulture.CompareInfo.Compare(this, strB, CompareOptions.None);
           }

    与类型参数为StringComparison.CurrentCulture的Compare方法相同。

    另外StringComparer也实现了字符串比较方法Compare()方法。直接看源代码:

    public int Compare(object x, object y)
          {
              if (x == y)
              {
                  return 0;
              }
              if (x == null)
              {
                  return -1;
              }
              if (y == null)
              {
                  return 1;
              }
              string str = x as string;
              if (str != null)
              {
                  string str2 = y as string;
                  if (str2 != null)
                  {
                      return this.Compare(str, str2);
                  }
              }
              IComparable comparable = x as IComparable;
              if (comparable == null)
              {
                  throw new ArgumentException(Environment.GetResourceString("Argument_ImplementIComparable"));
              }
              return comparable.CompareTo(y);
          }

    如果程序只将字符串用于内部编码目的,如路径名、文件名、URL、环境变量、反射、XML标记等,这些字符串通常只在程序内部使用,不会像用户展示,应该使用String.Ordinal或者使用String.CompareOrdinal()方法

    总结及建议:

    1. 使用显示地指定了字符串比较规则的重载函数。一般来说,需要带有StringComparison类型参数的重载函数
    2. 在对未知文化的字符串做比较时,使用StringComparison.Ordinal和StringComparison.OrdinallgnoreCase作为默认值,提高性能
    3. 在像用户输出结果时,使用基于StringComparison.CurrentCulture的字符串
    4. 使用String.Equals的重载版本来测试两个字符串是否相等。
    5. 不要使用String.Compare或CompareTo的重载版本来检测返回值是否为0来判断字符串是否相等。这两个函数是用于字符串比较,而非检查相等性。
    6. 在字符串比较时,应以String.ToUpperInvariant函数使字符串规范化,而不用ToLowerInvariant方法,因为Microsoft对执行大写比较的代码进行了优化。之所以不用ToUpper和ToLower方法,是因为其对语言文化敏感。

     转载 dudu 博客关于重定向解决方案深度透析:

    Response.Redirect引起的“无法在发送HTTP标头之后进行重定向”

     

    博客后台切换至i.cnblogs.com之后,在日志中发现大量的“无法在发送HTTP标头之后进行重定向”(Cannot redirect after HTTP headers have been sent)的错误信息。

    检查代码发现问题是由下面的代码触发的:

    复制代码
    IHttpHandler IHttpHandlerFactory.GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
    {
        context.Response.Redirect("http://i.cnblogs.com/" + 
            context.Request.RawUrl.Substring(context.Request.RawUrl.LastIndexOf("/") + 1));
    
        //后续也有context.Response.Redirect代码
        //...
        return PageParser.GetCompiledPageInstance(newurl, path, context);
    }
    复制代码

    “无法在发送HTTP标头之后进行重定向”问题来源于Response.Redirect之后,又进行了Response.Redirect。

    解决方法很简单:在Response.Redirect之后立即返回。

    复制代码
    IHttpHandler IHttpHandlerFactory.GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
    {
        context.Response.Redirect("http://i.cnblogs.com/" + 
            context.Request.RawUrl.Substring(context.Request.RawUrl.LastIndexOf("/") + 1));
        return null;
        //...    
    }
    复制代码

    为什么之前没有加return null呢?因为以前一直以为Response.Redirect会结束当前请求,不会执行Response.Redirect之后的代码。

    现在残酷的现实说明了不完全是这样的,那问题背后的真相是什么?让我们来一探究竟。

    由于微软公开了.NET Framework的源代码,现在无需再看Reflactor出来的代码,可以直接下载源代码用Visual Studio进行查看。

    .NET Framework源代码下载链接:http://referencesource.microsoft.com/download.html (相关新闻:微软开放了.NET 4.5.1的源代码

    用Visual Studio打开DotNetReferenceSourceSource dp.sln,搜索HttpResponse.cs,找到Response.Redirect的实现代码:

    public void Redirect(String url)
    {
        Redirect(url, true, false);
    }

    实际调用的是internal void Redirect(String url, bool endResponse, bool permanent) ,传给endResponse的值的确是true啊,为什么后面的代码还会执行?

    进一步查看internal void Redirect()的实现代码(省略了无关代码):

    复制代码
    internal void Redirect(String url, bool endResponse, bool permanent) 
    {
        //...
    
        Page page = _context.Handler as Page;
        if ((page != null) && page.IsCallback) {
            //抛异常
        }
    
        // ... url处理
    
        Clear(); //Clears all headers and content output from the buffer stream.
    
        //...
        this.StatusCode = permanent ? 301 : 302; //进行重定向操作
        //...
        _isRequestBeingRedirected = true; 
    
        var redirectingHandler = Redirecting;
        if (redirectingHandler != null) {
            redirectingHandler(this, EventArgs.Empty);
        }
    
        if (endResponse)
            End(); //结束当前请求
    }
    复制代码

    从上面的代码可以看出,我们要找的真相在End()方法中,继续看HttpResponse.End()的实现代码:

    复制代码
    public void End() {
        if (_context.IsInCancellablePeriod) {
            AbortCurrentThread();
        }
        else {
            // when cannot abort execution, flush and supress further output
            _endRequiresObservation = true;
    
            if (!_flushing) { // ignore Reponse.End while flushing (in OnPreSendHeaders)
                Flush();
                _ended = true;
    
                if (_context.ApplicationInstance != null) {
                    _context.ApplicationInstance.CompleteRequest();
                }
            }
        }
    }
    复制代码

    注意啦!真相浮现了!

    以前一直以为的Response.Redirect会结束当前请求,就是上面的AbortCurrentThread()情况,如果将Response.Redirect放在try...catch中就会捕捉到ThreadAbortException异常。

    通常情况下,我们在WebForms的Page或MVC的Controller中进行Redirect,_context.IsInCancellablePeriod的值为true,执行的是AbortCurrentThread(),所以不会遇到这个问题。

    而我们现在的场景恰恰是因为_context.IsInCancellablePeriod的值为false,为什么会是false呢?

    进一步看一下_context.IsInCancellablePeriod的实现:

    private int _timeoutState; // 0=non-cancelable, 1=cancelable, -1=canceled
    
    internal bool IsInCancellablePeriod {
        get { return (Volatile.Read(ref _timeoutState) == 1); }
    }

    根据上面的代码,触发这个问题的条件是_timeoutState的值要么是0,要么是-1,根据我们的实际情况,应该是0=non-cancelable。

    再来看看我们的实际应用场景,我们是在实现IHttpHandlerFactory接口的GetHandler方法中进行Response.Redirect操作的,也就是说在这个阶段_timeoutState的值还没被设置(默认值就是0)。为了验证这个想法,继续看一下_timeoutState在哪个阶段设值的。

    Shift+F12找到所有引用_timeoutState的地方,在HttpConext中发现了设置_timeoutState的方法BeginCancellablePeriod,实现代码如下:

    复制代码
    internal void BeginCancellablePeriod() {
        // It could be caused by an exception in OnThreadStart
        if (Volatile.Read(ref _timeoutStartTimeUtcTicks) == -1) {
            SetStartTime();
        }
    
        Volatile.Write(ref _timeoutState, 1);
    }
    复制代码

    然后再Shift+F12找到了在HttpApplication.ExecuteStep()中调用了BeginCancellablePeriod():

    复制代码
    internal Exception ExecuteStep(IExecutionStep step, ref bool completedSynchronously) 
    {
        //..
        if (step.IsCancellable) {
            _context.BeginCancellablePeriod(); // request can be cancelled from this point
        }
        //..
    }
    复制代码

    从上面的代码可以看出,当step.IsCancellable为true时,会调用BeginCancellablePeriod(),就不会出现这个问题。

    而我们用到的IHttpHandlerFactory.GetHandler()所在的IExecutionStep的实现可能将IsCancellable设置为了false。

    那IHttpHandlerFactory.GetHandler()是在哪个IExecutionStep的实现中调用的呢?

    在园子里木宛城主的一篇写得非常棒的博文(ASP.NET那点不为人知的事)中找到了答案——MapHandlerExecutionStep:

    当执行到MapHandlerExecutionStep时会执行如下代码获取最终执行请求:context.Handler = this._application.MapHttpHandler()。HttpApplication对象的MapHttpHandler方法将根据配置文件结合请求类型和URL以调用相应的IHttpHandlerFactory来获取HttpHandler对象。

    我们再回到.NET Framework的源代码中看一看MapHandlerExecutionStep的实现:

    复制代码
    // execution step -- map HTTP handler (used to be a separate module)
    internal class MapHandlerExecutionStep : IExecutionStep {
        private HttpApplication _application;
    
        internal MapHandlerExecutionStep(HttpApplication app) {
            _application = app;
        }
    
        void IExecutionStep.Execute() {
            //...
        }
    
        bool IExecutionStep.CompletedSynchronously {
            get { return true;}
        }
    
        bool IExecutionStep.IsCancellable {
            get { return false; }
        }
    }
    复制代码

    看到有没有?IExecutionStep.IsCancellable返回的值是false。

    到此,水落石出,真相大白!

    请看大屏幕——

    由于MapHandlerExecutionStep(调用IHttpHandlerFactory.GetHandler()的地方)返回的IsCancellable的值是false,于是在HttpApplication.ExecuteStep()执行时没有调用_context.BeginCancellablePeriod()——也就是没有把_timeoutState设置为1,_context.IsInCancellablePeriod的值就是false。从而造成在Response.Redirect中进行Response.End()时没有执行AbortCurrentThread()(通常情况下都会执行这个)。于是代码继续执行,后面又来一次Response.Redirect,最终引发了——“无法在发送HTTP标头之后进行重定向”(Cannot redirect after HTTP headers have been sent)。

    2016-11-10 CMD命令大全

      1. cmd命令大全(第一部分)
          winver---------检查Windows版本 
          wmimgmt.msc----打开windows管理体系结构(WMI) 
          wupdmgr--------windows更新程序 
          wscript--------windows脚本宿主设置 
          write----------写字板 
          winmsd---------系统信息 
          wiaacmgr-------扫描仪和照相机向导 
          winchat--------XP自带局域网聊天
      2.  
        cmd命令大全(第二部分)
          mem.exe--------显示内存使用情况 
          Msconfig.exe---系统配置实用程序 
          mplayer2-------简易widnows media player 
          mspaint--------画图板 
          mstsc----------远程桌面连接 
          mplayer2-------媒体播放机 
          magnify--------放大镜实用程序 
          mmc------------打开控制台 
          mobsync--------同步命令
      3.  
        cmd命令大全(第三部分)
          dxdiag---------检查DirectX信息 
          drwtsn32------ 系统医生 
          devmgmt.msc--- 设备管理器 
          dfrg.msc-------磁盘碎片整理程序 
          diskmgmt.msc---磁盘管理实用程序 
          dcomcnfg-------打开系统组件服务 
          ddeshare-------打开DDE共享设置 
          dvdplay--------DVD播放器
      4.  
        cmd命令大全(第四部分)
          net stop messenger-----停止信使服务 
          net start messenger----开始信使服务 
          notepad--------打开记事本 
          nslookup-------网络管理的工具向导 
          ntbackup-------系统备份和还原 
          narrator-------屏幕“讲述人” 
          ntmsmgr.msc----移动存储管理器 
          ntmsoprq.msc---移动存储管理员操作请求 
          netstat -an----(TC)命令检查接口
      5.  
        cmd命令大全(第五部分)
          syncapp--------创建一个公文包 
          sysedit--------系统配置编辑器 
          sigverif-------文件签名验证程序 
          sndrec32-------录音机 
          shrpubw--------创建共享文件夹 
          secpol.m转载自电脑十万个为什么http://www.qq880.com,请保留此标记sc-----本地安全策略 
          syskey---------系统加密,一旦加密就不能解开,保护windows xp系统的双重密码 
          services.msc---本地服务设置 
          Sndvol32-------音量控制程序 
          sfc.exe--------系统文件检查器 
          sfc /scannow---windows文件保护
      6.  
        cmd命令大全(第六部分)
          tsshutdn-------60秒倒计时关机命令 
          tourstart------xp简介(安装完成后出现的漫游xp程序) 
          taskmgr--------任务管理器 
          eventvwr-------事件查看器 
          eudcedit-------造字程序 
          explorer-------打开资源管理器 
          packager-------对象包装程序 
          perfmon.msc----计算机性能监测程序 
          progman--------程序管理器 
          regedit.exe----注册表 
          rsop.msc-------组策略结果集 
          regedt32-------注册表编辑器 
          rononce -p ----15秒关机 
          regsvr32 /u *.dll----停止dll文件运行 
          regsvr32 /u zipfldr.dll------取消ZIP支持
      7.  
        cmd命令大全(第七部分)
          cmd.exe--------CMD命令提示符 
          chkdsk.exe-----Chkdsk磁盘检查 
          certmgr.msc----证书管理实用程序 
          calc-----------启动计算器 
          charmap--------启动字符映射表 
          cliconfg-------SQL SERVER 客户端网络实用程序 
          Clipbrd--------剪贴板查看器 
          conf-----------启动netmeeting 
          compmgmt.msc---计算机管理 
          cleanmgr-------垃圾整理 
          ciadv.msc------索引服务程序 
          osk------------打开屏幕键盘 
          odbcad32-------ODBC数据源管理器 
          oobe/msoobe /a----检查XP是否激活 
          lusrmgr.msc----本机用户和组 
          logoff---------注销命令 
          iexpress-------木马捆绑工具,系统自带 
          Nslookup-------IP地址侦测器 
          fsmgmt.msc-----共享文件夹管理器 
          utilman--------辅助工具管理器 
          gpedit.msc-----组策略
        cmd命令大全/cmd命令提示符大全
         
  • 相关阅读:
    Peer code review
    分析图书管理系统的5W1H
    项目风险分析作业
    课堂练习
    功能分析四个象限
    Android需求分析作业
    电梯演说模板练习
    敏捷流程的理解
    团队模型的小组辩论
    结对编程任意Demo
  • 原文地址:https://www.cnblogs.com/workstation-liunianguowang/p/5884434.html
Copyright © 2020-2023  润新知