msgbartop
msgbarbottom

24 一 07 数学方法、逻辑判断实现、Ajax和密码强度

以下部分转贴一个Blog的文章。
一个名叫viBlogging的blog系统中需要的一个功能:在用户注册时根据输入的密码来显示密码强度(模仿passport的,不过是使用Atlas)。
对于密码强度,分为弱、中、强三等级,我的判断规则是:

1。如果密码的位数在3~4位之间,如果只含有字母,那么强度为弱。
2。如果密码的位数在3~4位之间,如果还含有数字,那么强度也为弱。
3。如果密码的位数在3~4位之间,如果含有非字母数字的字符,那么强度为中。
4。如果密码位数在5~7之间,只含有字母的强度为弱
5。如果密码位数在5~7之间,同时还有数字的强度为中。
6。如果密码位数在5~7之间,同时还有非字母数字字符的强度为强。
7。如果密码长度大于7,如果只含有字母,那么强度为中。
8。如果密码长度大于7,如果还含有数字的话强度为中。
9。如果密码长度大于7,如果含有非字母数字字符的话,强度为强。

如果此时昨晚规则的分析后就着手写代码的话,那要写一堆if嵌套了。这样做的话,很可能会使得逻辑陷入混乱,很有可能一些情况就被忽略过去了。更为严重的是,这样写严重降低了代码的可读性。如果我必须用这样的方式来写,那我首先会去写unit test,其次再附详细的doc或注释来说明。

Okay,那我们进一步来分析一下。我们上述的9个条件都是由密码长度和密码复杂度两部分来结合判断出来的。那么我们可以拆分一下,如下图所示(请大家先只看第一个表格):
点击在新窗口中浏览此图片
我们现在写两个函数,分别计算长度和复杂度对应的强度,并返回。这里我们用{0,1,2}和{0,1,3}来表示(为什么后者是{0,1,3}在后面会讲到)那么我们可以很容易把上面的9个规则总结成第一个表格来表示。

到这里为止,我可以分别使用i和j来表示拆分后的强度的表示,好,现在我们可以去写清晰一点的if..else嵌套或if..switch嵌套了,这里我们可以用标识符了,采用了简单的分而治之的思想,整个规则也被简化为了7步了(读者可以自己考虑一下),思路清晰了许多。

但是目前为止,我们还是没有脱离嵌套条件分支语句的尴尬和不便

Okay,我们继续对这个逻辑的返回结果作分析:
强度:情况1,情况2 = {(i1,j1),(i2,j2),....} § [(i+j)min,(i+j)max]
Strong: F,I = {(!0,3)} § [4,5]
Medium: G,E,H,C = {(2,0),(!0,1),(3,0)} § [2,3]
Weak: A,B,D = {(0,!3),(1,0)} § [0,1]

好,这样结果就很清楚了,当返回的i+j在>3时,那么强度肯定是strong的,如果小于2,那么肯定是weak的,剩下的就是Medium的了。这样只要写一个switch就完成任务了(我只在有双分支的时候用if,2个以上的都用switch,学过编译原理的应该知道它比if效率高,可是.net中他俩有什么性能区别我不知道,但是如果不出意外,应该还是比if效率高吧)。

此文仅在提供一种分解问题和归类问题各部分结果的小方法,当然也有“运气成分”(这就是为什么用{0,1,3}不用{0,1,2}的原因)。抛砖引玉,希望能学到更好的解决办法。

接下来是通过JS来实现判断密码强度:

   <script type="text/javascript">
       var PasswordStrength ={
           Level : ["高,实在是高","还行啦","靠,这样也行"],
           LevelValue : [30,20,0],//强度值
           Factor : [1,2,5],//字符加数,分别为字母,数字,其它
           KindFactor : [0,0,10,20],//密码含几种组成的加数
           Regex : [/[a-zA-Z]/g,/\d/g,/[^a-zA-Z0-9]/g] //字符正则数字正则其它正则
           }
       PasswordStrength.StrengthValue = function(pwd)
       {
           var strengthValue = 0;
           var ComposedKind = 0;
           for(var i = 0 ; i < this.Regex.length;i++)
           {
               var chars = pwd.match(this.Regex[i]);
               if(chars != null)
               {
                   strengthValue += chars.length * this.Factor[i];
                   ComposedKind ++;
               }
           }
           strengthValue += this.KindFactor[ComposedKind];
           return strengthValue;
       }
       PasswordStrength.StrengthLevel = function(pwd)
       {
           var value = this.StrengthValue(pwd);
           for(var i = 0 ; i < this.LevelValue.length ; i ++)
           {
               if(value >= this.LevelValue[i] )
                   return this.Level[i];
           }
       }
     
       alert(PasswordStrength.StrengthLevel("23"));
       alert(PasswordStrength.StrengthLevel("abcd123"));    
       alert(PasswordStrength.StrengthLevel("abcd!%23"));  
   </script>

最后,通过一个JS的类来实现检测密码强度:
点击这里下载文件
Tags - , , , , , , , , ,

24 一 07 数学方法、逻辑判断实现、Ajax和密码强度

以下部分转贴一个Blog的文章。
一个名叫viBlogging的blog系统中需要的一个功能:在用户注册时根据输入的密码来显示密码强度(模仿passport的,不过是使用Atlas)。
对于密码强度,分为弱、中、强三等级,我的判断规则是:

1。如果密码的位数在3~4位之间,如果只含有字母,那么强度为弱。
2。如果密码的位数在3~4位之间,如果还含有数字,那么强度也为弱。
3。如果密码的位数在3~4位之间,如果含有非字母数字的字符,那么强度为中。
4。如果密码位数在5~7之间,只含有字母的强度为弱
5。如果密码位数在5~7之间,同时还有数字的强度为中。
6。如果密码位数在5~7之间,同时还有非字母数字字符的强度为强。
7。如果密码长度大于7,如果只含有字母,那么强度为中。
8。如果密码长度大于7,如果还含有数字的话强度为中。
9。如果密码长度大于7,如果含有非字母数字字符的话,强度为强。

如果此时昨晚规则的分析后就着手写代码的话,那要写一堆if嵌套了。这样做的话,很可能会使得逻辑陷入混乱,很有可能一些情况就被忽略过去了。更为严重的是,这样写严重降低了代码的可读性。如果我必须用这样的方式来写,那我首先会去写unit test,其次再附详细的doc或注释来说明。

Okay,那我们进一步来分析一下。我们上述的9个条件都是由密码长度和密码复杂度两部分来结合判断出来的。那么我们可以拆分一下,如下图所示(请大家先只看第一个表格):
点击在新窗口中浏览此图片
我们现在写两个函数,分别计算长度和复杂度对应的强度,并返回。这里我们用{0,1,2}和{0,1,3}来表示(为什么后者是{0,1,3}在后面会讲到)那么我们可以很容易把上面的9个规则总结成第一个表格来表示。

到这里为止,我可以分别使用i和j来表示拆分后的强度的表示,好,现在我们可以去写清晰一点的if..else嵌套或if..switch嵌套了,这里我们可以用标识符了,采用了简单的分而治之的思想,整个规则也被简化为了7步了(读者可以自己考虑一下),思路清晰了许多。

但是目前为止,我们还是没有脱离嵌套条件分支语句的尴尬和不便

Okay,我们继续对这个逻辑的返回结果作分析:
强度:情况1,情况2 = {(i1,j1),(i2,j2),....} § [(i+j)min,(i+j)max]
Strong: F,I = {(!0,3)} § [4,5]
Medium: G,E,H,C = {(2,0),(!0,1),(3,0)} § [2,3]
Weak: A,B,D = {(0,!3),(1,0)} § [0,1]

好,这样结果就很清楚了,当返回的i+j在>3时,那么强度肯定是strong的,如果小于2,那么肯定是weak的,剩下的就是Medium的了。这样只要写一个switch就完成任务了(我只在有双分支的时候用if,2个以上的都用switch,学过编译原理的应该知道它比if效率高,可是.net中他俩有什么性能区别我不知道,但是如果不出意外,应该还是比if效率高吧)。

此文仅在提供一种分解问题和归类问题各部分结果的小方法,当然也有“运气成分”(这就是为什么用{0,1,3}不用{0,1,2}的原因)。抛砖引玉,希望能学到更好的解决办法。

接下来是通过JS来实现判断密码强度:

   <script type="text/javascript">
       var PasswordStrength ={
           Level : ["高,实在是高","还行啦","靠,这样也行"],
           LevelValue : [30,20,0],//强度值
           Factor : [1,2,5],//字符加数,分别为字母,数字,其它
           KindFactor : [0,0,10,20],//密码含几种组成的加数
           Regex : [/[a-zA-Z]/g,/\d/g,/[^a-zA-Z0-9]/g] //字符正则数字正则其它正则
           }
       PasswordStrength.StrengthValue = function(pwd)
       {
           var strengthValue = 0;
           var ComposedKind = 0;
           for(var i = 0 ; i < this.Regex.length;i++)
           {
               var chars = pwd.match(this.Regex[i]);
               if(chars != null)
               {
                   strengthValue += chars.length * this.Factor[i];
                   ComposedKind ++;
               }
           }
           strengthValue += this.KindFactor[ComposedKind];
           return strengthValue;
       }
       PasswordStrength.StrengthLevel = function(pwd)
       {
           var value = this.StrengthValue(pwd);
           for(var i = 0 ; i < this.LevelValue.length ; i ++)
           {
               if(value >= this.LevelValue[i] )
                   return this.Level[i];
           }
       }
     
       alert(PasswordStrength.StrengthLevel("23"));
       alert(PasswordStrength.StrengthLevel("abcd123"));    
       alert(PasswordStrength.StrengthLevel("abcd!%23"));  
   </script>

最后,通过一个JS的类来实现检测密码强度:
点击这里下载文件
Tags - , , , , , , , , ,

18 一 07 为Javascript数组添加一个inArray方法

了解 PHP 的朋友都知道, PHP 里面有个很好用的函数叫“in_array”,它可以用来检查数组中是否存在某个值,本文介绍的是通过 prototype 向 javascript 数组添加一个类似的方法,简单但是实用。
<script type="text/javascript">
Array.prototype.inArray = function (value) {
// Returns true if the passed value is found in the
// array.  Returns false if it is not.
  var i;
  for (i=0; i < this.length; i++) {
    // Matches identical (===), not just similar (==).
    if (this[i] === value) {
      return true;
    }
  }
  return false;
};
</script>

Tags - , , , ,

18 一 07 为Javascript数组添加一个inArray方法

了解 PHP 的朋友都知道, PHP 里面有个很好用的函数叫“in_array”,它可以用来检查数组中是否存在某个值,本文介绍的是通过 prototype 向 javascript 数组添加一个类似的方法,简单但是实用。
<script type="text/javascript">
Array.prototype.inArray = function (value) {
// Returns true if the passed value is found in the
// array.  Returns false if it is not.
  var i;
  for (i=0; i < this.length; i++) {
    // Matches identical (===), not just similar (==).
    if (this[i] === value) {
      return true;
    }
  }
  return false;
};
</script>

Tags - , , , ,

16 一 07 如何阻止表单重复提交、防刷新、防后退

这个问题有几种解决方案如下。
1 服务器端的解决方法。这是我最为推荐的方法。优点是判断准确,兼容性最大。
做法:a页面显示表单,然后提交b页面处理,处理完后重定向到c页面显示结果。

1.0 在访问a页面时在session里生成一个标志ID,例如
//伪代码
session("submitID")=random()

然后把这个值写到表单的一个hidden的input里
//伪代码
<%response.write("<input name=submitID2 type=hidden value=\""+session("submitID")+"\">")%>

1.1 b页面处理时判断表单所提交的submitID2的值是否和session中的submitID一致,不一致的话重定向到报错页面,一致的话把session中的submitID清空然后进行表单处理
//伪代码
session("submitID")=""
//然后处理提交......

处理完成后重定向到c页面

1.2 c页面其实就没什么好说的了,就是一个显示处理结果的页面。

2 客户端用js解决
这种方法不好,因为必然会遇到不同浏览器的兼容性问题,而且是必然可以绕过的。唯一的优点就是简单,不需要太多的编码

2.0防止后退
在每个页面的最顶上加上这个代码
<script>window.history.forward();</script>

2.1防止刷新
我很难想到什么好方法可以做到。因为要屏蔽的地方太多了。只好采用一种很烂的方法:
<body onunload="location='about:blank'>" <!-- 这个方法只是个想法,没有经过调试 -->

Tags - , , , , , , , ,

14 一 07 使用JSLint完成JavaScript语法检查

JSLint是一个JavaScript验证工具(www.jslint.com),可以扫描JavaScript源代码来查找问题。如果JSLint发现一个问题,JSLint就会显示描述这个问题的消息,并指出错误在源代码中的大致位置。有些编码风格约定可能导致未预见的行为或错误,JSLint除了能指出这些不合理的约定,还能标志出结构方面的问题。尽管JSLint不能保证逻辑一定正确,但确实有助于发现错误,这些错误很可能导致浏览器的JavaScript引擎抛出错误。
JSLint定义了一组编码约定,这比ECMA定义的语言更为严格。这些编码约定汲取了多年来的丰富编码经验,并以一条年代久远的编程原则作为宗旨:能做并不意味着应该做。JSLint会对它认为有风险的编码实践加标志,另外还会指出哪些是明显的错误(见下图),从而促使你养成好的JavaScript编码习惯。
点击在新窗口中浏览此图片
JSLint可能会把一些结构方面的错误标志为可疑的编码实践,以下列出了其中一部分(完整的列表可以参考JSLint的文档)。
引用
  JSLint要求所有代码行都以分号结束。尽管JavaScript确实允许将换行符作为行结束符,但一般认为这种做法是不明确的,而且是不好的编码风格。
  使用if和for的语句必须使用大括号把语句块括起来。
  不同于其他编程语言,在JavaScript中,块不会作为变量的作用域。JavaScript只支持函数级作用域。因此,JSLint只接受作为function、if、switch、while、for、do和try语句一部分的块,其他的块都会标志为错误。
  var只能声明一次,而且在使用之前必须声明。
  JSLint会把出现在return、break、continue或throw语句后面的代码标志为不可达的代码。这些语句后面必须紧跟一个结束大括号。

对于JavaScript程序员新手来说,JSLint是一个非常好的工具,因为它会教你一些好的JavaScript编码实践。由于JSLint能把可能导致逻辑错误或其他未预见行为的部分标出来,因此可以减少调试时间。如果你调试一段JavaScript代码时遇到困难,可以试试JSLint。
Tags - , , ,

12 一 07 多行文本框内字符换行的办法

<textarea name="ry" cols="60" rows="4">
<?=$text?>
</textarea>

如上,如果变量$text中需要换行,怎么办呢?
可以在程序中将$text中需要换行的地方加上html实体“& # 1 3”,即可在输出的时候形成在文本框中换行的结果。
Tags - , , , , ,

12 一 07 多行文本框内字符换行的办法

<textarea name="ry" cols="60" rows="4">
<?=$text?>
</textarea>

如上,如果变量$text中需要换行,怎么办呢?
可以在程序中将$text中需要换行的地方加上html实体“& # 1 3”,即可在输出的时候形成在文本框中换行的结果。
Tags - , , , , ,

09 一 07 10个重要的PHP网络信息函数说明

PHP与网页结合得如此紧密,以致于很容易忘记这种语言还可用来执行其它功能——数据加密、窗口应用与接口编程就是其中三个例子。既然网络编程是大多数开发者最可能遇到麻烦的领域,所以值得花时间来浏览一下PHP的内置网络函数,了解它们提供的功能,以及它如何帮助您完成下一个项目。
下面列出了PHP中的10个最有趣、最有用的网络函数,它是您了解PHP网络编程功能的起点,并为您进入多数网络开发者通常并未涉及的领域提供启示。每个函数都有说明与用法实例,为您说明在何时,该怎样应用这些函数。
getmxrr($hostname, $mxhosts)
该函数用来恢复某个特定主机的MX(邮件交换记录)主机名称。用这个函数来确认某个域的邮件主机,通常以验证那个域上的一个邮箱开始。
<?php
$hosts = array();
$ret = getmxrr('techrepublic.com', $hosts);
if ($ret) {
print_r($hosts);
} else {
echo 'MX retrieval failed';
}
?>

输出:
引用

Array (

[0] => c10-mail.cnet.com

[1] => c12-mail.cnet.com

)

gethostbyaddr($ip)
该函数用来恢复与一个IP有关的主机名。用此函数执行一个逆DNS查找,把一个名称给某个IP地址——如记录您的网络服务器日志的IP地址。
<?php
echo gethostbyaddr
('216.239.115.148');
?>

输出:
引用
c10-sha-redirect-lb.cnet.com

gethostbyname($name)
该函数与gethostbyaddr()函数互逆,恢复与主机有关的IP地址。用此函数执行一个标准的DNS查找,获得与IP地址有关的主机名——例如自动将有疑点的域列入黑名单时。
<?php
echo gethostbyname('techrepublic.com');
?>

输出:
引用
216.239.115.148

ip2long($ip)long2ip($long)
这些函数将由符号连接的四个小于255的数字代表的IP地址转换成整数,或进行逆操作。在需要用整数格式表示IP地址(通常用于数字计算),或用IP地址表示数字格式时,应用这些函数。
<?php
echo ip2long('216.239.115.148');
echo long2ip(-655395948);
?>

输出:
引用
-655395948
216.239.115.148

checkdnsrr($host, $type)
该函数在DNS中检查与$host主机相符的$type类型记录,如发现,即返回布尔真值。用此函数检查主机中是否存在某个特定的DNS记录类型。
<?php
$ret = checkdnsrr('techrepublic.com', SOA);
if ($ret) {
echo 'SOA records exist for host';
} else {
echo 'SOA records do not exist for host';
}
?>

输出:
引用
SOA records exist for host

dns_get_record($host, $type)
该函数返回$host主机的DNS记录。可选的$type参数只可用来恢复那些与一个特定的类型匹配的子集。用此函数恢复某个特殊主机的详细DNS记录。
<?php
$data = dns_get_record('techrepublic.com');
print_r($data);
?>

输出:
引用
Array
(
[0] => Array
(
[host] =>
techrepublic.com
[type] => MX
[pri] => 500
[target] =>
c10-mail.cnet.com
[class] => IN
[ttl] => 10756
)
[1] => Array
(
[host] =>
techrepublic.com
[type] => NS
[target] =>
ns3.cnet.com
[class] => IN
[ttl] => 7885
)
)

getprotobyname($num)getprotobynum($name)
这些函数从泛系统/etc/protocols文件中恢复协议名称与号码。用这些函数根据名称或号码来恢复系统协议信息。
<?php
echo getprotobyname(81);
echo getprotobyname('icmp');
?>

输出:
引用
vmtp
1

getservbyname($service,$protocol)
该函数利用$protocol协议,从泛系统/etc/services文件中为$service服务恢复端口号码。用此函数自动获得运行系统服务的端口信息。
<?php
echo getservbyname('http', 'tcp');
?>

输出:
引用
80

inet_ntop($addr)inet_pton($addr)
这些函数在二进制与人可读地址间转换IP地址。用此函数在Ipv4/Ipv6地址字符串与二进制表达法间进行转换。
<?php
$packed = inet_pton('192.168.0.1');
$unpacked = inet_ntop($packed);
echo $unpacked;
?>

输出:
引用
192.168.0.1

syslog($level, $msg)
这个函数利用警告级别$level将$msg信息记录到系统日志设备中。用此函数发布泛系统错误或警告。
<?php
define_syslog_variables();
openlog('mylog', LOG_NDELAY, LOG_LOCAL0);
syslog(LOG_DEBUG, 'This is a debug message');
closelog();
?>

Tags - , , , ,

09 一 07 10个重要的PHP网络信息函数说明

PHP与网页结合得如此紧密,以致于很容易忘记这种语言还可用来执行其它功能——数据加密、窗口应用与接口编程就是其中三个例子。既然网络编程是大多数开发者最可能遇到麻烦的领域,所以值得花时间来浏览一下PHP的内置网络函数,了解它们提供的功能,以及它如何帮助您完成下一个项目。
下面列出了PHP中的10个最有趣、最有用的网络函数,它是您了解PHP网络编程功能的起点,并为您进入多数网络开发者通常并未涉及的领域提供启示。每个函数都有说明与用法实例,为您说明在何时,该怎样应用这些函数。
getmxrr($hostname, $mxhosts)
该函数用来恢复某个特定主机的MX(邮件交换记录)主机名称。用这个函数来确认某个域的邮件主机,通常以验证那个域上的一个邮箱开始。
<?php
$hosts = array();
$ret = getmxrr('techrepublic.com', $hosts);
if ($ret) {
print_r($hosts);
} else {
echo 'MX retrieval failed';
}
?>

输出:
引用

Array (

[0] => c10-mail.cnet.com

[1] => c12-mail.cnet.com

)

gethostbyaddr($ip)
该函数用来恢复与一个IP有关的主机名。用此函数执行一个逆DNS查找,把一个名称给某个IP地址——如记录您的网络服务器日志的IP地址。
<?php
echo gethostbyaddr
('216.239.115.148');
?>

输出:
引用
c10-sha-redirect-lb.cnet.com

gethostbyname($name)
该函数与gethostbyaddr()函数互逆,恢复与主机有关的IP地址。用此函数执行一个标准的DNS查找,获得与IP地址有关的主机名——例如自动将有疑点的域列入黑名单时。
<?php
echo gethostbyname('techrepublic.com');
?>

输出:
引用
216.239.115.148

ip2long($ip)long2ip($long)
这些函数将由符号连接的四个小于255的数字代表的IP地址转换成整数,或进行逆操作。在需要用整数格式表示IP地址(通常用于数字计算),或用IP地址表示数字格式时,应用这些函数。
<?php
echo ip2long('216.239.115.148');
echo long2ip(-655395948);
?>

输出:
引用
-655395948
216.239.115.148

checkdnsrr($host, $type)
该函数在DNS中检查与$host主机相符的$type类型记录,如发现,即返回布尔真值。用此函数检查主机中是否存在某个特定的DNS记录类型。
<?php
$ret = checkdnsrr('techrepublic.com', SOA);
if ($ret) {
echo 'SOA records exist for host';
} else {
echo 'SOA records do not exist for host';
}
?>

输出:
引用
SOA records exist for host

dns_get_record($host, $type)
该函数返回$host主机的DNS记录。可选的$type参数只可用来恢复那些与一个特定的类型匹配的子集。用此函数恢复某个特殊主机的详细DNS记录。
<?php
$data = dns_get_record('techrepublic.com');
print_r($data);
?>

输出:
引用
Array
(
[0] => Array
(
[host] =>
techrepublic.com
[type] => MX
[pri] => 500
[target] =>
c10-mail.cnet.com
[class] => IN
[ttl] => 10756
)
[1] => Array
(
[host] =>
techrepublic.com
[type] => NS
[target] =>
ns3.cnet.com
[class] => IN
[ttl] => 7885
)
)

getprotobyname($num)getprotobynum($name)
这些函数从泛系统/etc/protocols文件中恢复协议名称与号码。用这些函数根据名称或号码来恢复系统协议信息。
<?php
echo getprotobyname(81);
echo getprotobyname('icmp');
?>

输出:
引用
vmtp
1

getservbyname($service,$protocol)
该函数利用$protocol协议,从泛系统/etc/services文件中为$service服务恢复端口号码。用此函数自动获得运行系统服务的端口信息。
<?php
echo getservbyname('http', 'tcp');
?>

输出:
引用
80

inet_ntop($addr)inet_pton($addr)
这些函数在二进制与人可读地址间转换IP地址。用此函数在Ipv4/Ipv6地址字符串与二进制表达法间进行转换。
<?php
$packed = inet_pton('192.168.0.1');
$unpacked = inet_ntop($packed);
echo $unpacked;
?>

输出:
引用
192.168.0.1

syslog($level, $msg)
这个函数利用警告级别$level将$msg信息记录到系统日志设备中。用此函数发布泛系统错误或警告。
<?php
define_syslog_variables();
openlog('mylog', LOG_NDELAY, LOG_LOCAL0);
syslog(LOG_DEBUG, 'This is a debug message');
closelog();
?>

Tags - , , , ,