利用PHP&VBS辅助,彻底抵挡CC攻击

常见的CC攻击是通过大量代理向网站发送大量的访问请求以致网站宕机,手段之可恶可耻程度非同一般!而本人对此恶劣手段又是恨之入骨! 

通常要很好的抵挡CC攻击的方法是使用天价的硬件防火墙(如IPS)再配合相对廉价的软件防火墙(如冰盾)之类方能阻挡大部分攻击,但对于一些没条件的机房(如普通电信机房)咱们就只能眼睁睁的看着网站“倒闭”了…… 

金庸的武侠小说中有一句至理名言:“欲练神功,必先自宫”,今天便练一招“七伤拳”,拳谱口决如下: 

一、从APNIC机构下载IP分配表至本地:ftp://ftp.apnic.net/apnic/dbase/data/country-ipv4.lst 

二、使用下面的PHP脚本分两步生成一个VBS脚本文件,脚本的作用是批量添加IIS允许访问的IP(程序未经精心修改,略显粗糙) 

<?php
/*
Get IP address of a designated country & Create a VBS script for Security IP in IIS
Author: Leon Lin
Data: 2009/12/19
*/
class ipv4
{
  /*
  IPv4 class
  Example:
  $ip = new ipv4("58.14.0.0",15);
  print "Address: ".$ip->address()."<br />";
  print "Netbits: ".$ip->netbits()."<br />";
  print "Netmask: ".$ip->netmask()."<br />";
  print "Inverse: ".$ip->inverse()."<br />";
  print "Network: ".$ip->network()."<br />";
  print "Broadcast: ".$ip->broadcast()."<br />";
  */
  var $address;
  var $netbits; 

  // Create new class
  function ipv4($address,$netbits)
  {
    $this->address = $address;
    $this->netbits = $netbits;
  } 

  // Return the IP address
  function address() { return ($this->address); } 

  // Return the netbits
  function netbits() { return ($this->netbits); } 

  // Return the netmask
  function netmask()
  {
    return (long2ip(ip2long("255.255.255.255")
           << (32-$this->netbits)));
  } 

  // Return the network that the address sits in
  function network()
  {
    return (long2ip((ip2long($this->address))
           & (ip2long($this->netmask()))));
  } 

  // Return the broadcast that the address sits in
  function broadcast()
  {
    return (long2ip(ip2long($this->network())
           | (~(ip2long($this->netmask())))));
  } 

  // Return the inverse mask of the netmask
  function inverse()
  {
    return (long2ip(~(ip2long("255.255.255.255")
           << (32-$this->netbits))));
  } 

}�
//Create file: Grant IP script for IIS
if ($_GET['act']=='getvbs')
{
 $vbsFunStr = "Sub AddGrantIP(strWebNo, strGrantIp)\r\nOn Error Resume Next\r\nSet SecObj = GetObject(\"IIS://LocalHost/W3SVC/\" & strWebNo & \"/Root\")\r\nSet MyIPSec = SecObj.IPSecurity\r\nMyIPSec.GrantByDefault = False\r\nIPList = MyIPSec.IPGrant\r\ni = UBound(IPList) + 1\r\nReDim Preserve IPList(i)\r\nIPList(i) = strGrantIp\r\nMyIPSec.IPGrant = IPList\r\nSecObj.IPSecurity = MyIPSec\r\nSecObj.Setinfo\r\nEnd Sub\r\n";
 $handleVBS=fopen('./IpGrant_for_IIS.vbs','a+');
 if (!fwrite($handleVBS,$vbsFunStr)) echo 'create vbs file false!<br />';
 $handle=fopen('./cnip.txt','r');
 if ($handle) {
     while (!feof($handle)) {
         $buffer = explode('/', fgets($handle));
         if (count($buffer)==2)
         {
          $ip = new ipv4($buffer[0],$buffer[1]);
          $ipStr = 'AddGrantIP "6","'.$ip->address().','.$ip->netmask()."\"\r\n";
          if (!fwrite($handleVBS,$ipStr)) echo 'false';
         }
     }
     fclose($handle);
 }else{
  echo 'unread ip file.';
 }
 echo 'create vbs file successful!';
} 

//Create file: IP lists for china
//Source from ftp://ftp.apnic.net/apnic/dbase/data/country-ipv4.lst
if ($_GET['act']=='getiplist')
{
 $file = file('./country-ipv4.lst');
 $handle = fopen('./cnip.txt', 'a');
 if($handle) {
     foreach ($file as $key => $val) {
         if (strpos($val, '#') !== 0) {
             $ipLines = explode(' ', $val);
             if ($ipLines[6] == 'cn') {
              $bits = explode('/', $ipLines[4]);
                 fputs($handle, $ipLines[0] ."/". $bits[1]. "\r\n");
             }
         }
     }
 }
 echo 'create china ip list successful!';
}
?>

备注:代码$ipStr = ‘AddGrantIP “6”,”‘.$ip->address().’,’.$ip->netmask().”\”\r\n”;其中的数字6是代表IIS站点列表中的站点标识符 

使用步骤:第一步 ?act=getiplist 生成中国IP地址段(cn);第二步 ?act=getvbs 生成VBS批量添加IIS允许访问的IP段文件;第三步 将VBS文件拷至服务器中双击执行一次。 

经此设置后我们便达到了“双残”的目的:攻击者使用的代理中凡是非中国IP均“被拒绝攻击”从而保护了站点的正常运作倘若攻击者使用中国的代理来攻击那你便拔110吧;而同时我们的网站也将只能允许中国用户的访问了。 

附相关参考资料:VBScript使用ADSI为IIS批量添加屏蔽或允许访问的IP

PHP获取中国IP段范围

去这个地址下载全球ip段   ftp://ftp.apnic.net/apnic/dbase/data/country-ipv4.lst
里面cn是中国ip段范围

新建一个php文件叫cnip.php

<?php
$file = file('./country-ipv4.lst');
$handle = fopen('./cnip.txt', 'a');
if($handle) {
    foreach ($file as $key => $val) {
        if (strpos($val, '#') !== 0) {
            $ipLines = explode(' ', $val);
            if ($ipLines[6] == 'cn') {
                fputs($handle, $ipLines[0]. '-'. $ipLines[2]. "\n");
            }
        }
    }
}
?>

打开cnip.txt 中国的ip段范围就有了,
如果是在window环境下,将 fputs($handle, $ipLines[0]. ‘-‘. $ipLines[2]. “\n”); 中的”\n”改为”\r\n”即可换行

VBScript使用ADSI为IIS批量添加屏蔽或允许访问的IP

'/*=========================================================================  
' * Intro       VBScript使用ADSI为IIS批量添加屏蔽或允许访问的IP  
' * FileName    VBScript-ADSI-IIS-Add-Deny-Grant-IP-Change-MetaBase.xml.vbs  
' * Author      yongfa365  
' * Version     v1.0  
' * WEB         http://www.yongfa365.com  
' * Email       yongfa365[at]qq.com  
' * FirstWrite  http://www.yongfa365.com/Item/ADSI-IIS-Add-Deny-Grant-IP.vbs.html  
' * From        http://blog.csdn.net/linyu/archive/2008/11/14/3300454.aspx  
' * MadeTime    2008-12-08 23:10:45  
' * LastModify  2008-12-08 23:10:45  
' *==========================================================================*/  
 
'AddDenyIP2All "192.168.1.106,255.255.255.0"  
'AddDenyIP2All "127.0.0.1"  
'AddDenyIP "123456","127.0.0.1"  
 
 
'添加要屏蔽的IP或一组计算机,到一个指定站点上  
 
Sub AddDenyIP(strWebNo, strDenyIp)  
    On Error Resume Next 
    Set SecObj = GetObject("IIS://LocalHost/W3SVC/" & strWebNo & "/Root")  
    Set MyIPSec = SecObj.IPSecurity  
    MyIPSec.GrantByDefault = True 
    IPList = MyIPSec.IPDeny  
    i = UBound(IPList) + 1  
    ReDim Preserve IPList(i)  
    IPList(i) = strDenyIp  
    MyIPSec.IPDeny = IPList  
    SecObj.IPSecurity = MyIPSec  
    SecObj.Setinfo  
End Sub 
 
 
'添加要屏蔽的IP或一组计算机,到IIS公共配置,以应用到所有站点  
'如果之前对有些站点单独做过屏蔽IP设置,在些设置不会生效,得在总的网站上设置一下,然后覆盖所有子结点  
 
Sub AddDenyIP2All(strDenyIp)  
    On Error Resume Next 
    Set SecObj = GetObject("IIS://LocalHost/W3SVC")  
    Set MyIPSec = SecObj.IPSecurity  
    MyIPSec.GrantByDefault = True 
    IPList = MyIPSec.IPDeny  
    i = UBound(IPList) + 1  
    ReDim Preserve IPList(i)  
    IPList(i) = strDenyIp  
    MyIPSec.IPDeny = IPList  
    SecObj.IPSecurity = MyIPSec  
    SecObj.Setinfo  
End Sub 
 
 
 
 
 
 
'添加允许的IP或一组计算机,到一个指定站点上  
 
Sub AddGrantIP(strWebNo, strGrantIp)  
    On Error Resume Next 
    Set SecObj = GetObject("IIS://LocalHost/W3SVC/" & strWebNo & "/Root")  
    Set MyIPSec = SecObj.IPSecurity  
    MyIPSec.GrantByDefault = False 
    IPList = MyIPSec.IPGrant  
    i = UBound(IPList) + 1  
    ReDim Preserve IPList(i)  
    IPList(i) = strGrantIp  
    MyIPSec.IPGrant = IPList  
    SecObj.IPSecurity = MyIPSec  
    SecObj.Setinfo  
End Sub 
 
 
'添加允许的IP或一组计算机,到IIS公共配置,以应用到所有站点  
'如果之前对有些站点单独做过屏蔽IP设置,在些设置不会生效,得在总的网站上设置一下,然后覆盖所有子结点  
 
Sub AddGrantIP2All(strGrantIp)  
    On Error Resume Next 
    Set SecObj = GetObject("IIS://LocalHost/W3SVC")  
    Set MyIPSec = SecObj.IPSecurity  
    MyIPSec.GrantByDefault = False 
    IPList = MyIPSec.IPGrant  
    i = UBound(IPList) + 1  
    ReDim Preserve IPList(i)  
    IPList(i) = strGrantIp  
    MyIPSec.IPGrant = IPList  
    SecObj.IPSecurity = MyIPSec  
    SecObj.Setinfo  
End Sub 
 
 
 
'显示IIS公共配置里禁止访问的IP  
Sub ListDenyIP()  
    Set SecObj = GetObject("IIS://LocalHost/W3SVC")  
    Set MyIPSec = SecObj.IPSecurity  
    IPList = MyIPSec.IPDeny 'IPGrant/IPDeny  
    WScript.Echo Join(IPList, vbCrLf)  
'   For i = 0 To UBound(IPList)  
'       WScript.Echo i + 1 & "-->" & IPList(i)  
'   Next  
End Sub

两个无线网卡如何连接 实现共享上网

硬件条件:
笔记本或PC A 一个网卡,一个USB无线网卡
笔记本或PC B 一个网卡,一个内置无线网卡
一根从交换机上分下来的网线 连接到A或B的网卡上,这里咱们连接到A上。

只要拥有以下两个协议就可以实现

Microsoft 网络客户端
Internet 协议 (TCP/IP)
想通过无线网卡连接两台电脑,并实现共享上网,设置如下:
首先声名,网上提供的方法基本上都是对的,只是细节方面很多人没有提到,导致像我这样的“高手”也没连接成功

在A上设置:
右击桌面“网上邻居”选择“属性”进入 “网络连接”,选中“本地连接”及“无线网络连接”,右击 点击“桥接”,等会,设置完成。

接下来操作 连接网线的机器 A,右击“无线网络连接”–>属性–>无线网络配置–>添加–>SSID里随便输入一个名,如:yongfa365,数据加密选“已禁用”,其它默认–>确定–>高级–>选中“仅计算机到计算机(特定)”–>关闭

OK,都设置好了,接下来要注意了,很多人会在这出错。搜索不到A这台机器上的无线信号。

按我的操作来,在A机器上双击“无线网络连接”,连接刚才建立的”yongfa365″,这时一时还连接不上,同时我们到B机器上也双击“无线网络连接”,刷新网络列表,会看到“yongfa365”,。连接他,有时一次连接不上,再连接一次,连接上后,机器A也连接上了,但有时显示却是别的,如:按需求,未连接。。。不管他,这样一来,两台机器都可以上网了。

以上操作,如果不先让A连接自己机器上的无线网络,B就连接不上,不知道是不是A没有发信号所以B不知道有这么个无线网络呢?windows 2008上设置好后,其它机器上就可以直接连接上。推荐机器配置高的人使用 windows 2008,非常人性化

IP地址和子网掩码计算

*************
IP地址的分类:
*************

  任何一个0到127间的网络地址均是一个A类地址。
  任何一个128到191间的网络地址是一个B类地址。
  任何一个192到223间的网络地址是一个C类地址。
  任何一个第一个八位组在224到239间的网络地址是一个组播地址。
  任何一个专用I P网络均可以使用包括一个A类地址( 10.0.0.0 )、16个B类地址(从172.16.0.0到172.31.0.0 )和256个C类地址(从192.168.0.0到192.168.255.0 )在内的任何地址。

***************
子网掩码的计算:
***************

其实计算并不复杂。
以C类地址为例,自己找找规律。
掩码00000000,最大子网,相当于无子网。
掩码10000000,子网数2,可用0,每子网地址128,可用主机126。
掩码11000000,子网数4,可用2,每子网地址64,可用主机62。
掩码11100000,子网数8,可用6,每子网地址32,可用主机30。
掩码11110000,子网数16,可用14,每子网地址16,可用主机14。
掩码11111000,子网数32,可用30,每子网地址8,可用主机6。
掩码11111100,子网数64,可用62,每子网地址4,可用主机2。
可见,子网划分越多,地址浪费越多。
将掩码换算为十进制,可使用WINDOWS的计算器。
如掩码11100000,换算后是224,子网掩码就是255.255.255.224。
应根据主机最多的部门来确定子网大小,如果一个C类地址段不够用,就要涉及到路由、VLAN等技术,这里就不多说了。

****************************
子网掩码及主机段的十进制算法
****************************

首先要明确一些概念:

类范围:IP地址常采用点分十进制表示方法X.Y.Y.Y,在这里
X=1–126时称为A类地址;
X=128–191时称为B类地址;
X=192–223时称为C类地址;
如10.202.52.130因为X=10在1–126范围内所以称为A类地址
类默认子网掩码:A类为 255.0.0.0
B类为 255.255.0.0
C类为 255.255.255.0

当我们要划分子网用到子网掩码M时,类子网掩码的格式应为
A类为 255.M.0.0
B类为 255.255.M.0
C类为 255.255.255.M
M是相应的子网掩码如:255.255.255.240
十进制计算基数:256,等一下我们所有的十进制计算都要用256来进行。

[separator]

几个公式变量的说明:
Subnet_block:可分配子网块大小,指在某一子网掩码下的子网的块数。
Subnet_num:实际可分配子网数,指可分配子网块中要剔除首、尾两块,这是某一子网掩码下可分配的实际子网数量,它等于Subnet_block-2。
IP_block:每个子网可分配的IP地址块大小。
IP_num:每个子网实际可分配的IP地址数,因为每个子网的首、尾IP地址必须保留(一个为网络地址,一个为广播地址),所以它等于IP_block-2,IP_num也用于计算主机段
M:子网掩码(net mask)。
它们之间的公式如下:
M=256-IP_block
IP_block=256/Subnet_block,反之Subnet_block=256/IP_block
IP_num=IP_block-2
Subnet_num=Subnet_block-2
2的冥数:要熟练掌握2^8(256)以内的2的冥代表的十进制数,如128=2^7、64=2^6…,这可使我们立即推算出Subnet_block和IP_block数。

[separator]
现在我们举一些例子:

一、 已知所需子网数12,求实际子网数
解:这里实际子网数指Subnet_num,由于12最接近2的冥为16(2^4),即 Subnet_block=16,那么Subnet_num=16-2=14,故实际子网数为14。

二、已知一个B类子网每个子网主机数要达到60×255(约相当于X.Y.0.1–X.Y.59.254的数量)个,求子网掩码。
解:1、60接近2的冥为64(2^6),即,IP_block=64
2、子网掩码M=256-IP_block
=256-64=192
3、子网掩码格式B类是:255.255.M.0.
所以子网掩码为:255.255.192.0

三、 如果所需子网数为7,求子网掩码
解:1、7最接近2的冥为8,但8个Subnet_block因为要保留首、尾2个子网块,即 8-2=6<7,并不能达到所需子网数,所以应取2的冥为16,即Subnet_block=16
2、IP_block=256/Subnet_block=256/16=16
3、子网掩码M=256-IP_block=256-16=240。

四、 已知网络地址为211.134.12.0,要有4个子网,求子网掩码及主机段。
解:1、211.y.y.y是一个C类网,子网掩码格式为255.255.255.M
2、4个子网,4接近2的冥是8(2^3),所以Subnet_block=8
Subnet_num=8-2=6
3、IP_block=256/Subnet_block=256/8=32
4、子网掩码M=256-IP_block=256-32=224
5、所以子网掩码表示为255.255.255.224
6、因为子网块(Subnet_block)的首、尾两块不能使用,所以可分配6个子网块(Subnet_num),每块32个可分配主机块(IP_block)
即:32-63、64-95、96-127、128-159、160-191、192-223
首块(0-31)和尾块(224-255)不能使用
7、每个子网块中的可分配主机块又有首、尾两个不能使用(一个是子网网络地址,一个 是子网广播地址),所以主机段分别为:
33-62、65-94、97-126、129-158、161-190、193-222
8、所以子网掩码为255.255.255.224
主机段共6段为:211.134.12.33–211.134.12.62
211.134.12.65–211.134.12.94
211.134.12.97–211.134.12.126
211.134.12.129–211.134.12.158
211.134.12.161–211.134.12.190
211.134.12.193–211.134.12.222
可以任选其中的4段作为4个子网。

总之,只要理解了公式中的逻辑关系,就能很快计算出子网掩码,从而得出可分配的主机段,参加MCSE和CCNA考试的朋友使用这种方法可以顺利地通过相关试题的考试,而不用象记99乘法口诀表一样去背什么二进制掩码表了。 *************
IP地址的分类:
*************

  任何一个0到127间的网络地址均是一个A类地址。
  任何一个128到191间的网络地址是一个B类地址。
  任何一个192到223间的网络地址是一个C类地址。
  任何一个第一个八位组在224到239间的网络地址是一个组播地址。
  任何一个专用I P网络均可以使用包括一个A类地址( 10.0.0.0 )、16个B类地址(从172.16.0.0到172.31.0.0 )和256个C类地址(从192.168.0.0到192.168.255.0 )在内的任何地址。

***************
子网掩码的计算:
***************

其实计算并不复杂。
以C类地址为例,自己找找规律。
掩码00000000,最大子网,相当于无子网。
掩码10000000,子网数2,可用0,每子网地址128,可用主机126。
掩码11000000,子网数4,可用2,每子网地址64,可用主机62。
掩码11100000,子网数8,可用6,每子网地址32,可用主机30。
掩码11110000,子网数16,可用14,每子网地址16,可用主机14。
掩码11111000,子网数32,可用30,每子网地址8,可用主机6。
掩码11111100,子网数64,可用62,每子网地址4,可用主机2。
可见,子网划分越多,地址浪费越多。
将掩码换算为十进制,可使用WINDOWS的计算器。
如掩码11100000,换算后是224,子网掩码就是255.255.255.224。
应根据主机最多的部门来确定子网大小,如果一个C类地址段不够用,就要涉及到路由、VLAN等技术,这里就不多说了。

****************************
子网掩码及主机段的十进制算法
****************************

首先要明确一些概念:

类范围:IP地址常采用点分十进制表示方法X.Y.Y.Y,在这里
X=1–126时称为A类地址;
X=128–191时称为B类地址;
X=192–223时称为C类地址;
如10.202.52.130因为X=10在1–126范围内所以称为A类地址
类默认子网掩码:A类为 255.0.0.0
B类为 255.255.0.0
C类为 255.255.255.0

当我们要划分子网用到子网掩码M时,类子网掩码的格式应为
A类为 255.M.0.0
B类为 255.255.M.0
C类为 255.255.255.M
M是相应的子网掩码如:255.255.255.240
十进制计算基数:256,等一下我们所有的十进制计算都要用256来进行。

[separator]

几个公式变量的说明:
Subnet_block:可分配子网块大小,指在某一子网掩码下的子网的块数。
Subnet_num:实际可分配子网数,指可分配子网块中要剔除首、尾两块,这是某一子网掩码下可分配的实际子网数量,它等于Subnet_block-2。
IP_block:每个子网可分配的IP地址块大小。
IP_num:每个子网实际可分配的IP地址数,因为每个子网的首、尾IP地址必须保留(一个为网络地址,一个为广播地址),所以它等于IP_block-2,IP_num也用于计算主机段
M:子网掩码(net mask)。
它们之间的公式如下:
M=256-IP_block
IP_block=256/Subnet_block,反之Subnet_block=256/IP_block
IP_num=IP_block-2
Subnet_num=Subnet_block-2
2的冥数:要熟练掌握2^8(256)以内的2的冥代表的十进制数,如128=2^7、64=2^6…,这可使我们立即推算出Subnet_block和IP_block数。

[separator]

现在我们举一些例子:

一、 已知所需子网数12,求实际子网数
解:这里实际子网数指Subnet_num,由于12最接近2的冥为16(2^4),即 Subnet_block=16,那么Subnet_num=16-2=14,故实际子网数为14。

二、已知一个B类子网每个子网主机数要达到60×255(约相当于X.Y.0.1–X.Y.59.254的数量)个,求子网掩码。
解:1、60接近2的冥为64(2^6),即,IP_block=64
2、子网掩码M=256-IP_block
=256-64=192
3、子网掩码格式B类是:255.255.M.0.
所以子网掩码为:255.255.192.0

三、 如果所需子网数为7,求子网掩码
解:1、7最接近2的冥为8,但8个Subnet_block因为要保留首、尾2个子网块,即 8-2=6<7,并不能达到所需子网数,所以应取2的冥为16,即Subnet_block=16
2、IP_block=256/Subnet_block=256/16=16
3、子网掩码M=256-IP_block=256-16=240。

四、 已知网络地址为211.134.12.0,要有4个子网,求子网掩码及主机段。
解:1、211.y.y.y是一个C类网,子网掩码格式为255.255.255.M
2、4个子网,4接近2的冥是8(2^3),所以Subnet_block=8
Subnet_num=8-2=6
3、IP_block=256/Subnet_block=256/8=32
4、子网掩码M=256-IP_block=256-32=224
5、所以子网掩码表示为255.255.255.224
6、因为子网块(Subnet_block)的首、尾两块不能使用,所以可分配6个子网块(Subnet_num),每块32个可分配主机块(IP_block)
即:32-63、64-95、96-127、128-159、160-191、192-223
首块(0-31)和尾块(224-255)不能使用
7、每个子网块中的可分配主机块又有首、尾两个不能使用(一个是子网网络地址,一个 是子网广播地址),所以主机段分别为:
33-62、65-94、97-126、129-158、161-190、193-222
8、所以子网掩码为255.255.255.224
主机段共6段为:211.134.12.33–211.134.12.62
211.134.12.65–211.134.12.94
211.134.12.97–211.134.12.126
211.134.12.129–211.134.12.158
211.134.12.161–211.134.12.190
211.134.12.193–211.134.12.222
可以任选其中的4段作为4个子网。

总之,只要理解了公式中的逻辑关系,就能很快计算出子网掩码,从而得出可分配的主机段,参加MCSE和CCNA考试的朋友使用这种方法可以顺利地通过相关试题的考试,而不用象记99乘法口诀表一样去背什么二进制掩码表了。

关于MYSQL的一道笔试题

题目要求是这样的,假设有如下表(MySQL):

TABLE: test

id a b
1 4 2
2 1 2
3 1 3
4 3 2
5 1 5
6 1 2
7 4 -1
8 1 2

 写一条SQL语句,

选择所有a=1或b=2的记录,

使得a=1且b=2的记录排在最前面,

并且a=1且b=2的记录按id降序排列。

分析:

很显然,直接的order by方案是不行的。

那我们就需要把条件分割:把a=1 or b=2分割成(a=1 and b=2) or (a=1 and b!=2) or (a!=1 and b=2)

再把选择的结果union一下就可以得到想要的结果了。

关于(a=1 and b=2)记录按id的降序排列,需要用到order by,如果直接这么用:

SELECT ... FROM ... ORDER BY ... DESC UNION ...

是会报错的, 把前面的select语句加上括号,不会报错,但是达不到想要的效果(order by 不起作用)。

这个时候就要用到derived table了,不过别忘了给derived table取一个别名(alias)。

SELECT * FROM (
    SELECT * FROM `test` WHERE `a`=1 AND `b`=2 ORDER BY `id` DESC
) `ab` UNION
SELECT * FROM `test` WHERE (`a`=1 AND `b`!=2) OR (`a`!=1 AND `b`=2)

 运行结果:

id a b
8 1 2
6 1 2
2 1 2
1 4 2
3 1 3
4 3 2
5 1 5

Tracing record of CC attacks in PHP code

最近几天网站饱受魔鬼CC的折磨,不得已采取一些“侵犯私隐”的手段以便找出源头来报仇 :)

以下代码的作用是记录访问者的访问时间与及IP或代理IP信息:

$strTmp = 'TIME:'.date("Y-m-d H:i:s").' HTTP_X_CLUSTER_CLIENT_IP:'.$_SERVER["HTTP_X_CLUSTER_CLIENT_IP"];

$strTmp .= ' HTTP_X_FORWARDED_FOR:'.$_SERVER["HTTP_X_FORWARDED_FOR"];

$strTmp .= ' HTTP_CLIENT_IP:'.$_SERVER["HTTP_CLIENT_IP"];

$strTmp .= ' REMOTE_ADDR:'.$_SERVER["REMOTE_ADDR"]."\r\n";

$handst=fopen('./ips/ip_'.date("Y-m-d").'.txt','a+');

if (!fwrite($handst,$strTmp)) echo 'false';

备注:如果攻击者使用的是全是透明代理,那PHP也是策手无束的,只能通过软硬墙加以适当的保护,又或者升级服务器配置、服务器集群负载均衡,再或者是将网站完全静态化,以缓解攻击力度。

老手段新思维 常见DDOS攻击和防护

    作为破坏力较强的黑客攻击手段,DDoS是一种形式比较特殊的拒绝服务攻击。作为一种分布、协作的大规模攻击方式,它往往把受害目标锁定在大型Internet站点,例如商业公司、搜索引擎或政府部门网站。由于DDoS攻击的恶劣性,难以被侦测和控制,来势迅猛又令人难以防备,具有极大破坏力因此也广泛受到网络安全业界的关注。
  
    一、 DDoS攻击原理
    我们先来研究最常见的SYN攻击, SYN攻击属于DOS Denial of Servic攻击的一种,它利用TCP协议缺陷,通过发送大量的半连接请求,耗费CPU和内存资源。TCP协议建立连接的时候需要双方相互确认信息,来防止连接被伪造和精确控制整个数据传输过程数据完整有效。所以TCP协议采用三次握手建立一个连接。

    第一次握手:建立连接时,客户端发送syn包到服务器,并进入SYN_SEND状态,等待服务器确认;第二次握手:服务器收到syn包,确认客户的SYN 同时自己也发送一个SYN包 即SYN+ACK包,此时服务器进入SYN_RECV状态; 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。

    二 、DDoS攻击种类
    由于肉鸡的木马可以随时更新攻击的数据包和攻击方式,所以新的攻击更新非常快这里我们介绍几种常见的攻击的原理和方法

    1.SYN变种攻击:发送伪造源IP的SYN数据包但是数据包不是64字节而是上千字节,这种攻击会造成一些防火墙处理错误导致锁死,消耗服务器CPU内存的同时还会堵塞带宽。

    2.TCP混乱数据包攻击:发送伪造源IP的 TCP数据包,TCP头的TCP Flags 部分是混乱的可能是syn ,ack ,syn+ack ,syn+rst等等,会造成一些防火墙处理错误导致锁死,消耗服务器CPU内存的同时还会堵塞带宽。

    3.针对UDP协议攻击: 很多聊天室,视频音频软件,都是通过UDP数据包传输的,攻击者针对分析要攻击的网络软件协议,发送和正常数据一样的数据包,这种攻击非常难防护,一般防护墙通过拦截攻击数据包的特征码防护,但是这样会造成正常的数据包也会被拦截。

    4.针对WEB Server的多连接攻击:通过控制大量肉鸡同时连接访问网站,造成网站无法处理瘫痪,这种攻击和正常访问网站是一样的,只是瞬间访问量增加几十倍甚至上百倍,有些防火墙可以通过限制每个连接过来的IP连接数来防护,但是这样会造成正常用户稍微多打开几次网站也会被封。

    5.针对WEB Server的变种攻击: 通过控制大量肉鸡同时连接访问网站,一点连接将不间断发送一些特殊的GET访问请求,造成网站数据库或者某些页面耗费大量的CPU,这样通过限制每个连接过来的IP连接数进行防护的方法就失效了,因为每个肉鸡可能只建立一个或者只建立少量的连接。这种攻击非常难防护。

    6. 针对WEB Server的变种攻击: 通过控制大量肉鸡同时连接网站端口,但是不发送GET请求而是乱七八糟的字符,大部分防火墙分析攻击数据包前三个字节是GET字符然后来进行http协议的分析,这种攻击,不发送GET请求就可以绕过防火墙到达服务器,一般服务器都是共享带宽的,带宽不会超过10M ,所以大量的肉鸡攻击数据包就会把这台服务器的共享带宽堵塞造成服务器瘫痪,这种攻击也非常难防护,因为如果只简单的拦截客户端发送过来没有GET字符的数据包,会错误的封锁很多正常的数据包造成正常用户无法访问。

    7.针对游戏服务器的攻击:因为游戏服务器非常多,这里介绍最早也是影响最大的传奇游戏,传奇游戏分为登陆注册端口7000,人物选择端口7100,以及游戏运行端口7200、7300、7400等,因为游戏自己的协议设计的非常复杂,所以攻击的种类也花样倍出,大概有几十种之多,而且还在不断的发现新的攻击种类,这里介绍目前最普遍的假人攻击,假人攻击是通过肉鸡模拟游戏客户端进行自动注册、登陆、建立人物、进入游戏活动从数据协议层面模拟正常的游戏玩家,很难从游戏数据包来分析出哪些是攻击哪些是正常玩家。

    三、 DDoS防护
    以上介绍的几种最常见的攻击也是比较难防护的攻击。一般基于包过滤的防火墙只能分析每个数据包,或者有限的分析数据连接建立的状态,防护SYN或者变种的SYNACK攻击效果不错,但是不能从根本上来分析TCP、UDP协议和针对应用层的协议。比如http、游戏协议、软件视频音频协议。现在的新的攻击越来越多的针对应用层协议漏洞攻击,或者分析协议然后发送和正常数据包一样的数据,或者干脆模拟正常的数据流,单从数据包层面,分析每个数据包里面有什么数据,根本无法很好的防护新型的攻击。

    目前防护网络攻击效果比较好的有傲盾,黑洞,和金盾防火墙.傲盾是基于连接状态检测的防火墙,防护SYN攻击和SYN变种攻击、TCP混乱数据包攻击,效果都差不多。因为傲盾基于连接状态检测的防火墙,3-7类的涉及到网络软件自己的网络协议的效果会好一些。 根据傲盾实验室测试,针对UDP协议的攻击,基于连接状态检测的傲盾防火墙可以记录每个UDP包所属的连接,判断此连接是否登陆,是否通过验证,如果没有通过验证,无论发送的数据包是否合法都会被拦截掉。第4、5、6 种攻击,基于连接状态检测的傲盾防火墙可以彻底分析HTTP协议,分析每个数据包所归属的HTTP连接,此连接是否是正常请求,如果不是正常请求,就进行拦截。也可以在防火墙里设置HTTP验证标记,这样防火墙处理新的HTTP协议的时候会随机生成一个HTTP标记,肉鸡攻击的时候不会处理这个标记,正常的IE打开的时候,会处理这个标记,这样防火墙就可以区分是不是正常IE打开的网页。对于第7种攻击,基于连接状态检测的防火墙可以通过多种策略混合过滤来达到效果,比如可以判断这个登陆进来的连接有没有发送过非法的特殊攻击包,因为肉鸡模拟的攻击假人毕竟是程序控制的,动作很少或者一直重复甚至一直不动,这样就可以判断这个连接在游戏里的动作10秒内是不是一直重复,重复多少次,或者是不是一直不动,来达到封锁假人的效果。

    四、小结
    现在网络发展速度飞快,新攻击每个星期都会有,传统的防火墙只能通过设置传统的规则封IP,端口,封连接数或者按照连接的一些基本特征来封锁,很难对新的攻击做出第一时间的解决方案。防火墙和攻击是矛和盾的关系,防火墙必须做到像杀毒软件一样有迅速处理的机制才能真正把新攻击扼杀到摇篮之中。

什么是DDOS攻击及怎么抵抗DDOS攻击?

 

一、为何要DDOS?

    随着Internet互联网络带宽的增加和多种DDOS黑客工具的不断发布,DDOS拒绝服务攻击的实施越来越容易,DDOS攻击事件正在成上升趋势。出于商业竞争、打击报复和网络敲诈等多种因素,导致很多IDC托管机房、商业站点、游戏服务器、聊天网络等网络服务商长期以来一直被DDOS攻击所困扰,随之而来的是客户投诉、同虚拟主机用户受牵连、法律纠纷、商业损失等一系列问题,因此,解决DDOS攻击问题成为网络服务商必须考虑的头等大事。

二、什么是DDOS?

    DDOS是英文Distributed Denial of Service的缩写,意即“分布式拒绝服务”,那么什么又是拒绝服务(Denial of Service)呢?可以这么理解,凡是能导致合法用户不能够访问正常网络服务的行为都算是拒绝服务攻击。也就是说拒绝服务攻击的目的非常明确,就是要阻止合法用户对正常网络资源的访问,从而达成攻击者不可告人的目的。虽然同样是拒绝服务攻击,但是DDOS和DOS还是有所不同,DDOS的攻击策略侧重于通过很多“僵尸主机”(被攻击者入侵过或可间接利用的主机)向受害主机发送大量看似合法的网络包,从而造成网络阻塞或服务器资源耗尽而导致拒绝服务,分布式拒绝服务攻击一旦被实施,攻击网络包就会犹如洪水般涌向受害主机,从而把合法用户的网络包淹没,导致合法用户无法正常访问服务器的网络资源,因此,拒绝服务攻击又被称之为“洪水式攻击”,常见的DDOS攻击手段有SYN Flood、ACK Flood、UDP Flood、ICMP Flood、TCP Flood、Connections Flood、Script Flood、Proxy Flood等;而DOS则侧重于通过对主机特定漏洞的利用攻击导致网络栈失效、系统崩溃、主机死机而无法提供正常的网络服务功能,从而造成拒绝服务,常见的DOS攻击手段有TearDrop、Land、Jolt、IGMP Nuker、Boink、Smurf、Bonk、OOB等。就这两种拒绝服务攻击而言,危害较大的主要是DDOS攻击,原因是很难防范,至于DOS攻击,通过给主机服务器打补丁或安装防火墙软件就可以很好地防范,后文会详细介绍怎么对付DDOS攻击。

三、被DDOS了吗?

    DDOS的表现形式主要有两种,一种为流量攻击,主要是针对网络带宽的攻击,即大量攻击包导致网络带宽被阻塞,合法网络包被虚假的攻击包淹没而无法到达主机;另一种为资源耗尽攻击,主要是针对服务器主机的攻击,即通过大量攻击包导致主机的内存被耗尽或CPU被内核及应用程序占完而造成无法提供网络服务。

    如何判断网站是否遭受了流量攻击呢?可通过Ping命令来测试,若发现Ping超时或丢包严重(假定平时是正常的),则可能遭受了流量攻击,此时若发现和你的主机接在同一交换机上的服务器也访问不了了,基本可以确定是遭受了流量攻击。当然,这样测试的前提是你到服务器主机之间的ICMP协议没有被路由器和防火墙等设备屏蔽,否则可采取Telnet主机服务器的网络服务端口来测试,效果是一样的。不过有一点可以肯定,假如平时Ping你的主机服务器和接在同一交换机上的主机服务器都是正常的,突然都Ping不通了或者是严重丢包,那么假如可以排除网络故障因素的话则肯定是遭受了流量攻击,再一个流量攻击的典型现象是,一旦遭受流量攻击,会发现用远程终端连接网站服务器会失败。

    相对于流量攻击而言,资源耗尽攻击要容易判断一些,假如平时Ping网站主机和访问网站都是正常的,发现突然网站访问非常缓慢或无法访问了,而Ping还可以Ping通,则很可能遭受了资源耗尽攻击,此时若在服务器上用Netstat -na命令观察到有大量的SYN_RECEIVED、TIME_WAIT、FIN_WAIT_1等状态存在,而ESTABLISHED很少,则可判定肯定是遭受了资源耗尽攻击。还有一种属于资源耗尽攻击的现象是,Ping自己的网站主机Ping不通或者是丢包严重,而Ping与自己的主机在同一交换机上的服务器则正常,造成这种原因是网站主机遭受攻击后导致系统内核或某些应用程序CPU利用率达到100%无法回应Ping命令,其实带宽还是有的,否则就Ping不通接在同一交换机上的主机了。

    当前主要有三种流行的DDOS攻击:

    1、SYN/ACK Flood攻击:这种攻击方法是经典最有效的DDOS方法,可通杀各种系统的网络服务,主要是通过向受害主机发送大量伪造源IP和源端口的SYN或ACK包,导致主机的缓存资源被耗尽或忙于发送回应包而造成拒绝服务,由于源都是伪造的故追踪起来比较困难,缺点是实施起来有一定难度,需要高带宽的僵尸主机支持。少量的这种攻击会导致主机服务器无法访问,但却可以Ping的通,在服务器上用Netstat -na命令会观察到存在大量的SYN_RECEIVED状态,大量的这种攻击会导致Ping失败、TCP/IP栈失效,并会出现系统凝固现象,即不响应键盘和鼠标。普通防火墙大多无法抵御此种攻击。

    2、TCP全连接攻击:这种攻击是为了绕过常规防火墙的检查而设计的,一般情况下,常规防火墙大多具备过滤TearDrop、Land等DOS攻击的能力,但对于正常的TCP连接是放过的,殊不知很多网络服务程序(如:IIS、Apache等Web服务器)能接受的TCP连接数是有限的,一旦有大量的TCP连接,即便是正常的,也会导致网站访问非常缓慢甚至无法访问,TCP全连接攻击就是通过许多僵尸主机不断地与受害服务器建立大量的TCP连接,直到服务器的内存等资源被耗尽而被拖跨,从而造成拒绝服务,这种攻击的特点是可绕过一般防火墙的防护而达到攻击目的,缺点是需要找很多僵尸主机,并且由于僵尸主机的IP是暴露的,因此容易被追踪。

    3、刷Script脚本攻击:这种攻击主要是针对存在ASP、JSP、PHP、CGI等脚本程序,并调用MSSQLServer、MySQLServer、Oracle等数据库的网站系统而设计的,特征是和服务器建立正常的TCP连接,并不断的向脚本程序提交查询、列表等大量耗费数据库资源的调用,典型的以小博大的攻击方法。一般来说,提交一个GET或POST指令对客户端的耗费和带宽的占用是几乎可以忽略的,而服务器为处理此请求却可能要从上万条记录中去查出某个记录,这种处理过程对资源的耗费是很大的,常见的数据库服务器很少能支持数百个查询指令同时执行,而这对于客户端来说却是轻而易举的,因此攻击者只需通过Proxy代理向主机服务器大量递交查询指令,只需数分钟就会把服务器资源消耗掉而导致拒绝服务,常见的现象就是网站慢如蜗牛、ASP程序失效、PHP连接数据库失败、数据库主程序占用CPU偏高。这种攻击的特点是可以完全绕过普通的防火墙防护,轻松找一些Proxy代理就可实施攻击,缺点是对付只有静态页面的网站效果会大打折扣,并且有些Proxy会暴露攻击者的IP地址。

四、怎么抵御DDOS?

    对付DDOS是一个系统工程,想仅仅依靠某种系统或产品防住DDOS是不现实的,可以肯定的是,完全杜绝DDOS目前是不可能的,但通过适当的措施抵御90%的DDOS攻击是可以做到的,基于攻击和防御都有成本开销的缘故,若通过适当的办法增强了抵御DDOS的能力,也就意味着加大了攻击者的攻击成本,那么绝大多数攻击者将无法继续下去而放弃,也就相当于成功的抵御了DDOS攻击。以下几点是防御DDOS攻击几点:

    1、采用高性能的网络设备

    首先要保证网络设备不能成为瓶颈,因此选择路由器、交换机、硬件防火墙等设备的时候要尽量选用知名度高、口碑好的产品。再就是假如和网络提供商有特殊关系或协议的话就更好了,当大量攻击发生的时候请他们在网络接点处做一下流量限制来对抗某些种类的DDOS攻击是非常有效的。

    2、尽量避免NAT的使用

    无论是路由器还是硬件防护墙设备要尽量避免采用网络地址转换NAT的使用,因为采用此技术会较大降低网络通信能力,其实原因很简单,因为NAT需要对地址来回转换,转换过程中需要对网络包的校验和进行计算,因此浪费了很多CPU的时间,但有些时候必须使用NAT,那就没有好办法了。

    3、充足的网络带宽保证

    网络带宽直接决定了能抗受攻击的能力,假若仅仅有10M带宽的话,无论采取什么措施都很难对抗现在的SYNFlood攻击,当前至少要选择100M的共享带宽,最好的当然是挂在1000M的主干上了。但需要注意的是,主机上的网卡是1000M的并不意味着它的网络带宽就是千兆的,若把它接在100M的交换机上,它的实际带宽不会超过100M,再就是接在100M的带宽上也不等于就有了百兆的带宽,因为网络服务商很可能会在交换机上限制实际带宽为10M,这点一定要搞清楚。

    4、升级主机服务器硬件

    在有网络带宽保证的前提下,请尽量提升硬件配置,要有效对抗每秒10万个SYN攻击包,服务器的配置至少应该为:P4 2.4G/DDR512M/SCSI-HD,起关键作用的主要是CPU和内存,若有志强双CPU的话就用它吧,内存一定要选择DDR的高速内存,硬盘要尽量选择SCSI的,别只贪IDE价格不贵量还足的便宜,否则会付出高昂的性能代价,再就是网卡一定要选用3COM或Intel等名牌的,若是Realtek的还是用在自己的PC上吧。

    5、把网站做成静态页面

    大量事实证明,把网站尽可能做成静态页面,不仅能大大提高抗攻击能力,而且还给黑客入侵带来不少麻烦,至少到现在为止关于HTML的溢出还没出现,看看吧!新浪、搜狐、网易等门户网站主要都是静态页面,若你非需要动态脚本调用,那就把它弄到另外一台单独主机去,免的遭受攻击时连累主服务器,当然,适当放一些不做数据库调用脚本还是可以的,此外,最好在需要调用数据库的脚本中拒绝使用代理的访问,因为经验表明使用代理访问你网站的80%属于恶意行为。

    6、增强操作系统的TCP/IP栈

    Win2000和Win2003作为服务器操作系统,本身就具备一定的抵抗DDOS攻击的能力,只是默认状态下没有开启而已,若开启的话可抵挡约10000个SYN攻击包,若没有开启则仅能抵御数百个,具体怎么开启,自己去看微软的文章吧!《强化 TCP/IP 堆栈安全》。

    也许有的人会问,那我用的是Linux和FreeBSD怎么办?很简单,按照这篇文章去做吧!《SYN Cookies》。

    7、安装专业抗DDOS防火墙

    8、其他防御措施

    以上几条对抗DDOS建议,适合绝大多数拥有自己主机的用户,但假如采取以上措施后仍然不能解决DDOS问题,就有些麻烦了,可能需要更多投资,增加服务器数量并采用DNS轮巡或负载均衡技术,甚至需要购买七层交换机设备,从而使得抗DDOS攻击能力成倍提高,只要投资足够深入。

企业服务器日常维护知多少?

   为了能更好的使用和延长服务器的使用寿命,定期的对服务器进行维护是非常必要的。但是,在维护服务器的时候一定要小心的处理好维护的工作,否则出现错误的话就会影响很大。为了方便大家在维护中了解一些维护内容的同时又能避免出现错误。下面就收集了一些资料供大家参考。

  硬件维护

  1、储存设备的扩充

  当资源不断扩展的时候,服务器就需要更多的内存和硬盘容量来储存这些资源。所以,内存和硬盘的扩充是很常见的。增加内存前需要认定与服务器原有的内存的兼容性,最好是同一品牌的规格的内存。如果是服务器专用的ECC内存,则必须选用相同的内存,普通的SDRAM内存与ECC内存在同一台服务器上使用很可能会引起统严重出错。在增加硬盘以前,需要认定服务器是否有空余的硬盘支架、硬盘接口和电源接口,还有主板是否支持这种容量的硬盘。尤其需要注意,防止买来了设备却无法使用。

  2、设备的卸载和更换

  卸载和更换设备时的问题不大,需要注意的是有许多品牌服务器机箱的设计比较特殊,需要特殊的工具或机关才能打开,在卸机箱盖的时候,需要仔细看说明书,不要强行拆卸。另外,必须在完全断电、服务器接地良好的情况下进行,即使是支持热插拔的设备也是如此,以防止静电对设备造成损坏。

  3、除尘

  尘土是服务器最大的杀手,因此需要定期给服务器除尘。对于服务器来说,灰尘甚至是致命的。除尘方法与普通PC除尘方法相同,尤其要注意的是电源的除尘。

  软件维护

  1、操作系统的维护

  操作系统是服务器运行的软件基础,其重要性不言自明。多数服务器操作系统使用Windows 2003或Windows 2008Server作为操作系统,维护起来还是比较容易的。

  在Windows NT或Windows 2003 Server打开事件查看器,在系统日志、安全日志和应用程序日志中查看有没有特别异常的记录。现在网上的黑客越来越多了,因此需要到微软的网站上下载最新的Service Pack(升级服务包)安装上,将安全漏洞及时补上。

  2、网络服务的维护

  网络服务有很多,如WWW服务、DNS服务、DHCP服务、SMTP服务、FTP服务等,随着服务器提供的服务越来越多,系统也容易混乱,此时可能需要重新设定各个服务的参数,使之正常运行。

  3、数据库服务

  数据库经过长期的运行,需要调整数据库性能,使之进入最优化状态。数据库中的数据是最重要的,这些数据库如果丢失,损失是巨大的,因此需要定期来备份数据库,以防万一。

  4、用户数据

  经过频繁使用,服务器可能存放了大量的数据。这些数据是非常宝贵的资源,所以需要加以整理,并刻成光盘永久保存起来,即使服务器有故障,也能恢复数据。

数据库设计规范化的五个要求

   通常情况下,可以从两个方面来判断数据库是否设计的比较规范。一是看看是否拥有大量的窄表,二是宽表的数量是否足够的少。若符合这两个条件,则可以说明这个数据库的规范化水平还是比较高的。当然这是两个泛泛而谈的指标。为了达到数据库设计规范化的要求,一般来说,需要符合以下五个要求。

  要求一:表中应该避免可为空的列。

  虽然表中允许空列,但是,空字段是一种比较特殊的数据类型。数据库在处理的时候,需要进行特殊的处理。如此的话,就会增加数据库处理记录的复杂性。当表中有比较多的空字段时,在同等条件下,数据库处理的性能会降低许多。

  所以,虽然在数据库表设计的时候,允许表中具有空字段,但是,我们应该尽量避免。若确实需要的话,我们可以通过一些折中的方式,来处理这些空字段,让其对数据库性能的影响降低到最少。

  一是通过设置默认值的形式,来避免空字段的产生。如在一个人事管理系统中,有时候身份证号码字段可能允许为空。因为不是每个人都可以记住自己的身份证号码。而在员工报到的时候,可能身份证没有带在身边。所以,身份证号码字段往往不能及时提供。为此,身份证号码字段可以允许为空,以满足这些特殊情况的需要。但是,在数据库设计的时候,则可以做一些处理。如当用户没有输入内容的时候,则把这个字段的默认值设置为0或者为N/A。以避免空字段的产生。

  二是若一张表中,允许为空的列比较多,接近表全部列数的三分之一。而且,这些列在大部分情况下,都是可有可无的。若数据库管理员遇到这种情况,笔者建议另外建立一张副表,以保存这些列。然后通过关键字把主表跟这张副表关联起来。将数据存储在两个独立的表中使得主表的设计更为简单,同时也能够满足存储空值信息的需要。

  要求二:表不应该有重复的值或者列。

  如现在有一个进销存管理系统,这个系统中有一张产品基本信息表中。这个产品开发有时候可以是一个人完成,而有时候又需要多个人合作才能够完成。所以,在产品基本信息表产品开发者这个字段中,有时候可能需要填入多个开发者的名字。

  如进销存管理中,还需要对客户的联系人进行管理。有时候,企业可能只知道客户一个采购员的姓名。但是在必要的情况下,企业需要对客户的采购代表、仓库人员、财务人员共同进行管理。因为在订单上,可能需要填入采购代表的名字;可是在出货单上,则需要填入仓库管理人员的名字等等。

  为了解决这个问题,有多种实现方式。但是,若设计不合理的话在,则会导致重复的值或者列。如我们也可以这么设计,把客户信息、联系人都放入同一张表中。为了解决多个联系人的问题,可以设置第一联系人、第一联系人电话、第二联系人、第二联系人电话等等。若还有第三联系人、第四联系人等等,则往往还需要加入更多的字段。

  可是这么设计的话,会产生一系列的问题。如客户的采购员流动性比较大,在一年内换了六个采购员。此时,在系统中该如何管理呢?难道就建立六个联系人字段?这不但会导致空字段的增加,还需要频繁的更改数据库表结构。明显,这么做是不合理的。也有人说,可以直接修改采购员的名字呀。可是这么处理的话,会把原先采购订单上采购员的名字也改变了。因为采购单上客户采购员信息在数据库中存储的不是采购员的名字,而只是采购员对应的一个编号。在编号不改而名字改变了的情况下,采购订单上显示的就是更改后的名字。这不利于时候的追踪。

  所以,在数据库设计的时候要尽量避免这种重复的值或者列的产生。笔者建议,若数据库管理员遇到这种情况,可以改变一下策略。如把客户联系人另外设置一张表。然后通过客户ID把供应商信息表跟客户联系人信息表连接起来。也就是说,尽量将重复的值放置到一张独立的表中进行管理。然后通过视图或者其他手段把这些独立的表联系起来。

  要求三:表中记录应该有一个唯一的标识符。

  在数据库表设计的时候,数据库管理员应该养成一个好习惯,用一个ID号来唯一的标识行记录,而不要通过名字、编号等字段来对纪录进行区分。每个表都应该有一个ID列,任何两个记录都不可以共享同一个ID值。另外,这个ID值最好有数据库来进行自动管理,而不要把这个任务给前台应用程序。否则的话,很容易产生ID值不统一的情况。

  另外,在数据库设计的时候,最好还能够加入行号。如在销售订单管理中,ID号是用户不能够维护的。但是,行号用户就可以维护。如在销售订单的行中,用户可以通过调整行号的大小来对订单行进行排序。通常情况下,ID列是以1为单位递进的。但是,行号就要以10为单位累进。如此,正常情况下,行号就以10、20、30依次扩展下去。若此时用户需要把行号为30的纪录调到第一行显示。此时,用户在不能够更改ID列的情况下,可以更改行号来实现。如可以把行号改为1,在排序时就可以按行号来进行排序。如此的话,原来行号为30的纪录现在行号变为了1,就可以在第一行中显示。这是在实际应用程序设计中对ID列的一个有效补充。这个内容在教科书上是没有的。需要在实际应用程序设计中,才会掌握到这个技巧。

  要求四:数据库对象要有统一的前缀名。

  一个比较复杂的应用系统,其对应的数据库表往往以千计。若让数据库管理员看到对象名就了解这个数据库对象所起的作用,恐怕会比较困难。而且在数据库对象引用的时候,数据库管理员也会为不能迅速找到所需要的数据库对象而头疼。

  为此,笔者建立,在开发数据库之前,最好能够花一定的时间,去制定一个数据库对象的前缀命名规范。如笔者在数据库设计时,喜欢跟前台应用程序协商,确定合理的命名规范。笔者最常用的是根据前台应用程序的模块来定义后台数据库对象前缀名。如跟物料管理模块相关的表可以用M为前缀;而以订单管理相关的,则可以利用C作为前缀。具体采用什么前缀可以以用户的爱好而定义。但是,需要注意的是,这个命名规范应该在数据库管理员与前台应用程序开发者之间达成共识,并且严格按照这个命名规范来定义对象名。

  其次,表、视图、函数等最好也有统一的前缀。如视图可以用V为前缀,而函数则可以利用F为前缀。如此数据库管理员无论是在日常管理还是对象引用的时候,都能够在最短的时间内找到自己所需要的对象。

  要求五:尽量只存储单一实体类型的数据。

  这里将的实体类型跟数据类型不是一回事,要注意区分。这里讲的实体类型是指所需要描述对象的本身。笔者举一个例子,估计大家就可以明白其中的内容了。如现在有一个图书馆里系统,有图书基本信息、作者信息两个实体对象。若用户要把这两个实体对象信息放在同一张表中也是可以的。如可以把表设计成图书名字、图书作者等等。可是如此设计的话,会给后续的维护带来不少的麻烦。

  如当后续有图书出版时,则需要为每次出版的图书增加作者信息,这无疑会增加额外的存储空间,也会增加记录的长度。而且若作者的情况有所改变,如住址改变了以后,则还需要去更改每本书的记录。同时,若这个作者的图书从数据库中全部删除之后,这个作者的信息也就荡然无存了。很明显,这不符合数据库设计规范化的需求。

  遇到这种情况时,笔者建议可以把上面这张表分解成三种独立的表,分别为图书基本信息表、作者基本信息表、图书与作者对应表等等。如此设计以后,以上遇到的所有问题就都引刃而解了。

  以上五条是在数据库设计时达到规范化水平的基本要求。除了这些另外还有很多细节方面的要求,如数据类型、存储过程等等。而且,数据库规范往往没有技术方面的严格限制,主要依靠数据库管理员日常工作经验的累积。

据说是最健康的作息时间表

大部分IT相关人士的作息时间都不太规律,转载过来,仅供大家参考一下

7:30:起床。英国威斯敏斯特大学的研究人员发现,那些在早上5:22―7:21 分起床的人,其血液中有一种能引起心脏病的物质含量较高,因此,在7:21之后起床对身体健康更加有益。
打开台灯。“一醒来,就将灯打开,这样将会重新调整体内的生物钟,调整睡眠和醒来模式。”拉夫堡大学睡眠研究中心教授吉姆·霍恩说。
喝一杯水。水是身体内成千上万化学反应得以进行的必需物质。早上喝一杯清水,可以补充晚上的缺水状态。 
 
7:30―8:00:在早饭之前刷牙。“在早饭之前刷牙可以防止牙齿的腐蚀,因为刷牙之后,可以在牙齿外面涂上一层含氟的保护层。要么,就等早饭之后半小时再刷牙。”英国牙齿协会健康和安全研究人员戈登·沃特金斯说。 
 
8:00―8:30:吃早饭。“早饭必须吃,因为它可以帮助你维持血糖水平的稳定。”伦敦大学国王学院营养师凯文·威尔伦说。早饭可以吃燕麦粥等,这类食物具有较低的血糖指数。 
 
8:30―9:00:避免运动。来自布鲁奈尔大学的研究人员发现,在早晨进行锻炼的运动员更容易感染疾病,因为免疫系统在这个时间的功能最弱。步行上班。马萨诸塞州大学医学院的研究人员发现,每天走路的人,比那些久坐不运动的人患感冒病的几率低25%。 
 
9:30:开始一天中最困难的工作。纽约睡眠中心的研究人员发现,大部分人在每天醒来的一两个小时内头脑最清醒。 
 
10:30:让眼睛离开屏幕休息一下。如果你使用电脑工作,那么每工作一小时,就让眼睛休息3分钟。 
 
11:00:吃点水果。这是一种解决身体血糖下降的好方法。吃一个橙子或一些红色水果,这样做能同时补充体内的铁含量和维生素C含量。 
 
13:00:在面包上加一些豆类蔬菜。你需要一顿可口的午餐,并且能够缓慢地释放能量。“烘烤的豆类食品富含纤维素,番茄酱可以当作是蔬菜的一部分。”维伦博士说。 
 
14:30―15:30:午休一小会儿。雅典的一所大学研究发现,那些每天中午午休30分钟或更长时间,每周至少午休3次的人,因心脏病死亡的几率会下降37%。 
 
16:00:喝杯酸奶。这样做可以稳定血糖水平。在每天三餐之间喝些酸牛奶,有利于心脏健康。 
 
17:00―19:00:锻炼身体。根据体内的生物钟,这个时间是运动的最佳时间,舍菲尔德大学运动学医生瑞沃·尼克说。 
 
19:30:晚餐少吃点。晚饭吃太多,会引起血糖升高,并增加消化系统的负担,影响睡眠。晚饭应该多吃蔬菜,少吃富含卡路里和蛋白质的食物。吃饭时要细嚼慢咽。 
 
21:45:看会电视。这个时间看会儿电视放松一下,有助于睡眠,但要注意,尽量不要躺在床上看电视,这会影响睡眠质量。 
 
23:00:洗个热水澡。“体温的适当降低有助于放松和睡眠。”拉夫堡大学睡眠研究中心吉姆·霍恩教授说。 
 
23:30:上床睡觉。如果你早上7点30起床,现在入睡可以保证你享受8小时充足的睡眠。

 

【编者按】虽然没有必要一一照做,有的地方甚至与我们的学习和工作时间冲突很大,但这个作息时间表还是颇有参考价值的。我们只有一个身体,请善待之。

中国蓝客联盟整站源码(2004版)

一:网站管理登录方法:
1、点击网点右上解“Webmaster Login”
2、输入公用密码:helloluc
3、进入登录界面后再输入管理员帐户密码
  网站管理员:admin
  管理员密码:admin
二:数据库密码 luc01s
三:论坛版主设置方法:
1、登录后台进入论坛版块编辑
2、填写版主用户名
3、进入论坛会员管理,编辑刚才填写的版主的用户名,将“版主”选项打钩
四:后台登录界面不能查看验证码解决方法二侧:
1、注册表补丁文件:Xp SP2 Image.reg(传说中WindowsXP SP2操作系统不能查看验证码)
2、使用Firefox浏览器登录
本程序乃本人2004年初学ASP的新手作品,没有使用到ASP的高级技术,更与2009年的ASP程序是无法相比。
但程序使用了大量的条件判断和防SQL注入操作,比较适合新手参考学习。

公布原因:本程序由中国蓝客联盟蓝色飞飞(mkman)于2004年编写,多年来许多朋友问我要源码,但一直以来没有公布。

 

====点击下载文件:LUC2004.zip====

C#批处理图片尺寸(按文件夹)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Forms;
using System.Threading;

namespace ThumbnailImages
{
    public delegate void DelegateStart();
    public delegate void DelegateDoException(Exception ex);
    public delegate void DelegateThreadFinished(string message);
    public delegate void DelegateProgressBarPerformStep(int fileIndex, string filename);

    public partial class frmMain : Form
    {
        int width = 600, height = 600;
        int percent = -1;
        int totalFileCount = 0;
        private Thread timedProgress;
        string sourcePath, targetPath;
        string[] files;

        public DelegateStart DelegateStart;
        public DelegateDoException DelegateDoException;
        public DelegateThreadFinished DelegateThreadFinished;
        public DelegateProgressBarPerformStep DelegateProgressBarPerformStep;

        public frmMain()
        {
            InitializeComponent();
            this.cbDefined.SelectedIndex = 2;

            DelegateStart = new DelegateStart(this.Start);
            DelegateThreadFinished = new DelegateThreadFinished(this.ThreadFinished);
            DelegateDoException = new DelegateDoException(this.DoException);
            DelegateProgressBarPerformStep = new DelegateProgressBarPerformStep(this.ProgressBarPerformStep);

        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            string sourcePath = txtSource.Text;
            string targetPath = txtTarget.Text;
            if (sourcePath.Length == 0 || !Directory.Exists(sourcePath))
            {
                txtSource.Focus();
                MessageBox.Show("请重新选择图片文件夹!", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            if (targetPath.Length == 0)
            {
                txtTarget.Focus();
                MessageBox.Show("请重新选择图片保存路径!", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            if (!Directory.Exists(targetPath))
            {
                try
                {
                    Directory.CreateDirectory(targetPath);
                }
                catch
                {
                    txtTarget.Focus();
                    MessageBox.Show("请重新选择图片保存路径!", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }
            }

            GetImageSizeSetting();

            timedProgress = new Thread(new ThreadStart(TimedProgressProc));
            timedProgress.IsBackground = true;
            timedProgress.Start();

        }

        public void Start()
        {
            sourcePath = txtSource.Text;
            targetPath = txtTarget.Text;
            files = Directory.GetFiles(sourcePath);
            totalFileCount = files.Length;
            this.lblInfo.Text = string.Format("0/{0}", totalFileCount);
            this.progressBar.Maximum = totalFileCount;
            this.btnStart.Enabled = false;
            this.btnStop.Enabled = true;

        }

        public void ThreadFinished(string message)
        {
            if (MessageBox.Show(message, "系统提示", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes)
            {
                System.Diagnostics.Process.Start(targetPath);
            }
           
            this.btnStart.Enabled = true;
            this.btnStop.Enabled = false;
            this.progressBar.Value = 0;
            this.lblInfo.Text = "全部完成!";
        }
        public void DoException(Exception ex)
        {
            MessageBox.Show(ex.ToString(), "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
            this.btnStart.Enabled = true;
            this.btnStop.Enabled = false;
            this.progressBar.Value = 0;
        }
        public void ProgressBarPerformStep(int fileIndex, string filename)
        {
            progressBar.PerformStep();
            filename = Path.GetFileName(filename);
            this.lblInfo.Text = string.Format("{0}/{1}, 当前文件: {2}", fileIndex, totalFileCount, filename);
        }

        private void TimedProgressProc()
        {
            try
            {
                ImageCodecInfo icf = ImageHelper.GetImageCodecInfo(ImageFormat.Jpeg);

                Image image, thumbnailImage;
                string thumbnailImageFilename;
                this.Invoke(this.DelegateStart);
                int i = 0;
                foreach (string filename in files)
                {
                    if (timedProgress == null)
                        return;
                    //lblInfo.Text = string.Format("正在处理: {0} ", filename); ;
                    progressBar.Invoke(this.DelegateProgressBarPerformStep, new object[] { i++, filename });
                    string extension = Path.GetExtension(filename).ToLower();
                    if (extension != ".jpg"
                        && extension != ".jpeg"
                        && extension != ".gif"
                        && extension != ".bmp"
                        && extension != ".png"
                        )
                        continue;
                    try
                    {
                        using (image = Image.FromFile(filename))
                        {
                            Size imageSize = GetImageSize(image);

                            using (thumbnailImage = ImageHelper.GetThumbnailImage(image, imageSize.Width, imageSize.Height))
                            {
                                //thumbnailImageFilename = Path.GetFileNameWithoutExtension(filename) + "_" + thumbnailImage.Width + "x" + thumbnailImage.Height + extension;
                                thumbnailImageFilename = Path.GetFileNameWithoutExtension(filename) + extension;
                                ImageHelper.SaveImage(thumbnailImage, Path.Combine(targetPath, thumbnailImageFilename), icf);
                            }
                        }
                    }
                    catch(Exception ex)
                    {
                        string em = ex.Message;
                        //lblInfo.Text = string.Format("{0} 可能不是合法的图片文件!", filename);
                    }
                }
                this.Invoke(this.DelegateThreadFinished, new object[] { "已经全部完成!\n是否打开生成图片的所在文件夹?" });
            }
            catch (ThreadInterruptedException e)
            {
                return;
            }
            catch (Exception ex)
            {
                this.Invoke(this.DelegateDoException, new Object[] { ex });
            }

        }

        private Size GetImageSize(Image picture)
        {
            Size imageSize;
            if (percent > 0)
            {
                imageSize = new Size(picture.Width * percent / 100, picture.Height * percent / 100);
            }
            else
                imageSize = new Size(width, height);

            double heightRatio = (double)picture.Height / picture.Width;
            double widthRatio = (double)picture.Width / picture.Height;

            int desiredHeight = imageSize.Height;
            int desiredWidth = imageSize.Width;
            imageSize.Height = desiredHeight;
            if (widthRatio > 0)
                imageSize.Width = Convert.ToInt32(imageSize.Height * widthRatio);

            if (imageSize.Width > desiredWidth)
            {
                imageSize.Width = desiredWidth;
                imageSize.Height = Convert.ToInt32(imageSize.Width * heightRatio);
            }

            if (checkSmart.Checked == true)
            {
                if (picture.Width < imageSize.Width && picture.Height < imageSize.Height)
                {
                    imageSize.Width = picture.Width;
                    imageSize.Height = picture.Height;
                }
            }

            return imageSize;
        }

        private void GetImageSizeSetting()
        {
            if (rbDefined.Checked)
            {
                if (cbDefined.SelectedIndex == 0)
                {
                    width = 550;
                    height = 550;
                }
                else if (cbDefined.SelectedIndex == 1)
                {
                    width = 130;
                    height = 130;
                }
                else if (cbDefined.SelectedIndex == 2)
                {
                    width = 600;
                    height = 600;
                }
                else if (cbDefined.SelectedIndex == 3)
                {
                    width = 150;
                    height = 150;
                }
            }
            else if (rbCustom.Checked)
            {
                width = (int)numWidth.Value;
                height = (int)numHeight.Value;
            }
            else if (rbDefined.Checked)
            {
                percent = (int)numPercent.Value;
            }
        }

        private void cbDefined_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!rbDefined.Checked)
                rbDefined.Checked = true;
        }

        private void btnBrowserSource_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
            {
                txtSource.Text = folderBrowserDialog.SelectedPath;
                //if (txtTarget.Text.Length == 0)
                txtTarget.Text = Path.Combine(folderBrowserDialog.SelectedPath, "_处理后的图片");
            }
        }

        private void btnBrowserTarget_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
            {
                txtTarget.Text = folderBrowserDialog.SelectedPath;
            }
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            linkLabel1.LinkVisited = true;
            System.Diagnostics.Process.Start(http://www.phpker.com);
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            if (timedProgress != null)
            {
                timedProgress.Interrupt();
                timedProgress = null;
                ThreadFinished("已经取消!\n是否打开生成图片的所在文件夹?");
                this.lblInfo.Text = "已取消!";
            }
        }
    }
}

用ASP类快速文件上传及读取表单值

众所周知当form中有文件域时form编码类型必须设为multipart/form-data服务器端才能接收file的文件内容,但如此一来ASP便不能通过常规方法request.form(“inputName”)或者request(“inputName”)的方法读取表单值。

类文件内容
Filename:  formdata.class.asp
=====================

<%
'类型: 文件上传表单处理类
'名称: FormUpload
'变量: fileSize(允许上传文件尺寸)、fileType(允许上传文件类型)、savePath(上传文件夹名)、basePath(上传基本路径)、cutSize(图片压缩尺寸)、Upload(私有变量 ASPUPLOAD组件对象)
'成员: Begin()公共函数 类初始化、Post(表单名)公共函数 返回表单的值、Uploadfile(文件域名)公共函数 返回上传文件完整路径、CutImage(图片文件相对路径, 压缩尺寸)私有函数 压缩图片至指定的尺寸、Class_Terminate()析构函数 释放对象时自动执行释放ASPUPLOAD组件对象
'作者: Leon Lin
'时间: 2009-10-30
Class FormData
 dim fileSize '允许上传文件尺寸
 dim fileType '允许上传文件类型
 dim savePath '上传文件夹名
 dim basePath '上传基本路径
 dim cutSize  '图片压缩尺寸
 private Upload 'ASPUPLOAD组件对象
�
�
 '成员函数,初始化
 Public Sub Begin()
  Set Upload = Server.CreateObject("Persits.Upload")     '创建ASPUPLOAD组件对象
  Upload.IgnoreNoPost = True           '未触发POST时中断上传文件
  On Error Resume Next
  Upload.CodePage = 65001            'UTF-8编码
  Upload.SetMaxSize fileSize*1024, True        '上传文件大小限制
  Upload.CreateDirectory Server.MapPath(basePath&savePath), True  '创建上传目录
  Upload.Save()              '保存文件至内存中
 End Sub
�
�
 '成员函数,返回表单值
 Public Function Post(formField)
  Post = Upload.Form(formField)
 End Function
�
�
 '成员函数,上传文件域中的文件
 Public Function Uploadfile(fileField)
  if right(savePath, 1)<>"/" then savePath=savePath&"/"  '保存目录后加"/"
  '上传常规检查
  If Err.Number = 8 Then Call Warning("警告:文件大小限制 "&fileSize&"KB 以内!", "")
  If Err <> 0 Then Call Warning("警告:文件上传失败!", "")
  '必须选择一个文件才执行上传脚本
  If Not Upload.Files(fileField) Is Nothing Then
   Set File = Upload.Files(fileField)
   '检查所选文件是否存在
   if File.Size = 0 then
    Set File = nothing
    Call Warning("警告:请选择一个正确的文件!", "")
   end if
   '不允许文件扩展名为空
   if File.ext = "" then
    Set File = nothing
    Call Warning("警告:非法文件!", "")
   end if
   fileExt = lcase(File.ext)    '所上传的文件扩展名
   fileTypeStr = fileType&","    '处理接受搜索的扩展名列表
   '检查文件类型,匹配扩展名
   If Instr(fileTypeStr, replace(fileExt, ".", "")&",") <= 0 Then
    Set File = nothing
    Call Warning("警告:只允许上传 "&fileType&" 格式的文件!", "")
   End If
   '文件重命名
   randomize
   ranNum = int(900*rnd)+100
   reName = year(now)&month(now)&day(now)&hour(now)&minute(now)&second(now)&ranNum  '文件名
   fullFileName = basePath & savePath & reName & fileExt       '函数返回的文件完整路径
   File.SaveAs Server.MapPath(basePath) & "/" & savePath & reName & fileExt  '复制文件并重命名
   If File.ImageType = "UNKNOWN" Then IsImage = false : Else IsImage = true  '判断是否图片
   Set File = nothing
  End If
  if IsImage = true then
   Uploadfile = CutImage(fullFileName, cutSize)  '压缩图片并返回上传文件完整路径
  else
   Uploadfile = fullFileName
  end if
 End Function
�
�
 '析构函数,释放组件对象
 Private Sub Class_Terminate()
  Set Upload = nothing
 End Sub
�
�
 'ASPJPEG图片处理
 Private Function CutImage(src, cut)
  Set Jpeg = Server.CreateObject("Persits.Jpeg")
  Jpeg.Open Server.MapPath(src)
  If Jpeg.OriginalWidth >= cut Or Jpeg.OriginalHeight >= cut Then
   If Jpeg.OriginalWidth > Jpeg.OriginalHeight Then
      Jpeg.Width = cut
      Jpeg.Height = Jpeg.OriginalHeight * cut / Jpeg.OriginalWidth
   Else
      Jpeg.Height = cut
      Jpeg.Width = Jpeg.OriginalWidth * cut / Jpeg.OriginalHeight
   End If
   Jpeg.Save Server.MapPath(src)
  End if
  Set Jpeg = nothing
  CutImage = src
 End Function

End Class
%>

操作脚本
Filename: form.asp
======================

<%
 Set Form = new FormData
 Form.fileSize = 300
 Form.fileType = "jpg,gif,png"
 Form.savePath = "Photos/"
 Form.basePath = "../UploadFiles/"
 Form.cutSize = 600 '当上传的文件如果是图片类型侧自动按比例压缩图片
 Form.Begin()
 Filename = Form.Uploadfile("Photo") '使用Form.Uploadfile("文件域名称")上传文件
 response.write Form.Post("GoodsName") '使用Form.Post("表单名")读取表单的值
 Set Posts = nothing
%>

如此一来在多文件上传或在复杂的判断中上传文件就方便得多了。

备注:
代码中使用到两个ASP的常用组件(AspUpload和AspJpeg)下载地址分别为:
http://www.aspupload.com/
http://www.aspjpeg.com/
(至于破解版还请各位自己问GOOGLE,这里便不帖出来了)