mysql的char,varchar,text,blob是几个有联系但是有有很大区别的字段类型,这算是mysql的基础吧,可是基础没有学好,恶补一下。

先简单的总结一下:

char:定长,最大255个字符

varchar:变长,最大65535个字符(既是单列的限制,又是整行的限制)

text:变长,有字符集的大对象,并根据字符集进行排序和校验,大小写不敏感

blob:变长,无字符集的二进制大对象,大小写敏感

以下只是我个人的理解,才疏学浅,望各路高人指点。

我使用的引擎是myisam,所以以下的探讨是集中在myisam上的。

首先解释char,char是项目中常用的字段类型之一,它代表的含义是采用固定长度存储数据,换句话说,数据初始化的是就为该类型的字段分配固定长度的存储空间,即使没有达到存储空间的长度,实际占用的存储空间也是定义时的长度。举个例子来说,比如某字段 a     char(50),指定的长度是50个字符的存储空间,那么当你存入一个字符:“abc”的时候,实际上字符长度是3个字符,但是占用的硬盘空间还是50个字符。很显然,char的缺点就出来了:浪费存储空间!但是同时char的优点也显示出来了:固定长度,(索引)效率极高,不存在碎片

这里我们再探讨一下char的存储方式,虽然char会浪费极大的存储空间,但是你想过对于字符串的前后空格char是如何处理的吗?当存储的字符串没有达到char的最大长度时,字符串后面是不会以空格来填充的,而且char会过滤字符串末端的空格然后存储,而在比较字符串的时候又会自动空格填充到字符串的末端。

好了,对char有了了解以后,对varchar的理解也就容易了。

varchar是存储可变长度的字符串,简单的说我们定义表机构的时候指定的字段长度是最大长度,当字符串没有达到最大长度的时候以字符串的实际长度来存储的,不占用多余的存储空间。因此,一般情况下,varchar比char节省存储空间,但是也经常有例外,后面接着探讨这个问题。

一个特殊的情况是创建表的时候采用ROW_FORMAT=FIXED选项(默认的是ROW_FORMAT=DYNAMIC),那么mysql就会为每行数据分配固定长度的存储空间,当然这是特例。不知道你有没有想过:为什么有管理员愿意这样做呢?对varchar分配固定长度的存储空间是有道理的。举一个常见的例子,假设采用DYNAMIC默认选项,那么我们创建一个字段b  varchar(100),现在我们插入一个只有10个字符的数据:abcdefghij,很好,只占用了10个字符的空间,相比char节省了不少存储空间。但是你想到问题了吗?比如某天以后你发现这个字段需要更新一下,更新为20个字符的数据:abcdefghijklmnopqrst,你知道数据库该如何存储吗?原先的存储位置分配的只有10个字符的空间,现在要存储20个字符,小于长度限制(最大长度是100个字符),问题就来了,mysql会如何处理呢?这里接下来可能要探讨mysql存储层面的分页机制或者拆分机制,就不再继续深入了。总之无论mysql采取什么方式,肯定会在磁盘上形成碎片,久而久之形成的磁盘碎片对系统效率是一个致命的打击,所以我们经常看到有管理员要把mysql导出然后导入,就是为了解决这个问题,提高效率。

上面我们提出来了一个问题:varchar比char节省存储空间,但是也经常有例外!对于这个疑问我们如何理解呢?要深入分析这个问题,我们需要再次深入了解varchar的存储机制。常用的中文存储一般采用gbk或者utf-8两种字符集,gbk每个字符占2个字节,utf-8每个字符占3个字节,所以:gbk字符集的最大存储长度是

(65535-1-1)/2= 32766或者(65535-1-2)/2= 32766,这个算法的含义是:65535是varchar的最大长度,第一个-1表示实际存储位置是从第二位开始的,第二个-1或者-2代表的含义是:varchar 字段是将实际内容单独存储在聚簇索引之外,内容开头用1到2个字节表示实际长度(长度小于255时用1个字节,长度超过255时需要2个字节),除以2的原因是一个gbk字符集的字符占2个字节长度,所以根据情况可以得出gbk字符集的最大存储长度是32766。

那么UTF-8字符集呢?算法如下:

(65535-1-1)/3=  21844或者(65535-1-2)/3= 21844减1减2的含义同上,除以3的含义是一个utf-8的字符集字符占用实际长度是3个字节。

看完了这段你就能理解char(1)和varchar(1)占用的存储空间了吧?在这个极端情况下,很显然char更节省存储空间,因为char没有管理数据的额外开销。

接下来,我们重点探讨一下varchar的65535存储长度代表的真正含义是什么?因为前面说过一句话:既是单列的限制,又是整行的限制!我们详细来解释一下。对于单列的限制,我们举一个例子:create table tablename(c varchar(N)) charset=gbk;那么N的最大值是(65535-1-2)=32766。同时,如果同一个有其他字段的话,那么所有字段的长度和不能超过65535,举个例子:create table tablename(c1 int(4), c2 char(30), c3 varchar(N) ) charset=utf8,那么N的最大值是(65535-1-2-4-30*3)/3=21812,也许你很理解int(4)需要4个字符的位置,这里可能需要更深入的了解int的存储机制,我不太了解,书还没有看呢。总之int类型占用4个字符的长度,换句话说create table tablename(c1 int(32), c2 char(30), c3 varchar(N) ) charset=utf8,N的最大值也是(65535-1-2-4-30*3)/3=21812。我做了一个简单的实验,看截图。

第一张varchar的长度大于21812,于是失败了

第二张varchar长度等于21812,保存成功

转载请注明来源:www.blogguy.cn

废话了这么多,总之一句话:char在浪费存储空间的劣势下,获得了较高的效率,varchar相反。接下来我们也要总结一下什么情况下使用char,什么情况下使用varchar。

原则一:根据字符串长度确定,凡是固定长度的字符串或者类似固定长度的字符串一律用char。比如身份证号码,手机号码,银行卡号,MD5,哈希值等这是字符串是固定长度的,毫无疑问用char,还有一类是基本固定长度但是略有出入的,比如中国人的姓名等,一般长度可能是2~5个汉字,这类信息也非常适合用char来存储,只要分配一些略大于通常长度即可。

原则二:数据是否经常更改导致碎片,可能经常变动而产生存储碎片的小字符串一律用char。我们知道char类型的数据是一次性分配存储空间的,无论以后你怎么修改,数据始终在该存储空间内的,不会产生碎片。而varchar则不同,varchar的数据长度是可变的,当修改后的数据大于当前存储长度时,就会产生碎片,如果该应用是反复修改数据的应用,那么久而久之就是产生无数碎片,效率可想而知。

原则三:理解varchar的存储空间和内存空间的区别,合理指定varchar的长度。我们知道varchar的存储长度是根据字符串的长度而定的,但是运行时占用的内存空间却是按照定义的长度分配内存空间的(我的理解,不知道是否正确)。这个现象导致存储一个字符串,比如通信地址,通畅在100个字符内就能存储完成,于是varchar(100)是一个合理的选择,但是由于之前讲的,可能有人图方便使用varchar(500),反正用的存储空间是一样的,但是效果确实不一样的。在内存模型中varchar(100)与varchar(500)是两码事,后者比前者占用多5倍的内存空间,在临时表和排序的时候这个差别几乎可能差一个数量级,于是效率可想而知。

转载注明来源:www.varsoft.net

基本上解释完char和varchar,这里顺带看看Nchar和Nvarchar是什么?

nvarchar表示可变长度 Unicode 数据,其最大长度为 4,000 字符;nchar表示固定长度的 Unicode 数据,最大长度为 4,000 个字符。

那Nchar和Nvarchar在什么情况下使用呢?我们知道字符 中,英文字符只需要一个字节存储就足够了,但汉字众多,需要两个字节存储,英文与汉字同时存在时容易造成混乱,Unicode字符集就是为了解决字符集这 种不兼容的问题而产生的,它所有的字符都用两个字节表示,即英文字符也是用两个字节表示。于是支持多语言的站点应考虑使用 Unicode nchar 或 nvarchar 数据类型以尽量减少字符转换问题。同样的解释还有下面我们要研讨的NText。

下面我们看看text和blob

text分为4种类型:TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT,分别对应不同的长度。text是非二进制字符串,并且需要指定字符集,并按照该字符集进行校验和排序。只能存储纯文本,可以看作是VARCHAR在长度不足时的扩展。

blob也分为4种类型:TINYBLOB,BLOB,mediumblob和LongBlob,分别对应不同的长度,blob存储的是二进制数据,因此无需字符集校验,blob除了存储文本信息外,由于二进制存储格式,所以还可以保存图片等信息,blob可以看作是VARBINARY在长度不足时的扩展。

text和blob的各种类型存储长度,我们用如下的表格表示:

TinyBlob                             最大长度255个字元(2^8-1)  
TinyText                             最大长度255个字元(2^8-1)
Blob                                    最大长度65535个字元(2^16-1)
Text                                    最大长度65535个字元(2^16-1)
MediumBlob                         最大长度 16777215 个字元(2^24-1)
MediumText                         最大长度 16777215 个字元(2^24-1
LongBlob                              最大长度4294967295个字元 (2^32-1)
LongText                              最大长度4294967295个字元 (2^32-1)

好了,到此char,varchar,text,blob内容探讨基本完成了,下面是我再次复习一下有关int型数据的内容,列在这里方便对比。

XML/HTML代码

  1. • TINYINT——一个微小的整数,支持 -128到127(SIGNED),0到255(UNSIGNED),需要1个字节存储   

  2. • BIT——同TINYINT(1)   

  3. • BOOL——同TINYINT(1)   

  4. • SMALLINT——一个小整数,支持 -32768到32767(SIGNED),0到65535(UNSIGNED),需要2个字节存储 MEDIUMINT——一个中等整数,支持 -8388608到8388607(SIGNED),0到16777215(UNSIGNED),需要3个字节存储   

  5. • INT——一个整数,支持 -2147493648到2147493647(SIGNED),0到4294967295(UNSIGNED),需要4个字节存储   

  6. • INTEGER——同INT   

  7. • BIGINT——一个大整数,支持 -9223372036854775808到9223372036854775807(SIGNED),0到18446744073709551615(UNSIGNED),需要8个字节存储   

  8. • FLOAT(precision)——一个浮点数。precision<=24用于单精度浮点数;precision在25和53之间,用于又精度浮点数。FLOAT(X)与相诮的FLOAT和DOUBLE类型有差相同的范围,但是没有定义显示尺寸和小数位数。在MySQL3.23之前,这不是一个真的浮点值,且总是有两位小数。MySQL中的所有计算都用双精度,所以这会带来一些意想不到的问题。   

  9. • FLOAT——一个小的菜单精度浮点数。支持 -3.402823466E+38到-1.175494351E-38,0和1.175494351E-38 to 3.402823466E+38,需要4个字节存储。如果是UNSIGNED,正数的范围保持不变,但负数是不允许的。   

  10. • DOUBLE——一个双精度浮点数。支持 -1.7976931348623157E+308到-2.2250738585072014E-308,0和2.2250738585072014E-308到1.7976931348623157E+308。如果是FLOAT,UNSIGNED不会改变正数范围,但负数是不允许的。   

  11. • DOUBLE PRECISION——同DOUBLE   

  12. • REAL——同DOUBLE   

  13. • DECIMAL——将一个数像字符串那样存储,每个字符占一个字节   

  14. • DEC——同DECIMAL   

  15. • NUMERIC——同DECIMAL   

近来微博很火,因为字数的限制,出现了很多网址缩短这种服务,比如sina自己用了自家的sinaurl.cn,想到自己曾经也注册了一个很短的域名 jcu.cc 很久了,一直闲着,不知道干嘛用,突然想到可以用来做网址缩短,还不错。说干就干,一会就写好了。比如我的博客地址就可以缩短成 :  http://jcu.cc/tinyurl

程序的设计很简单,下面说下原理,

   数据库只有两个字段seq(自增长数字)和url(数字的url地址,建立索引)。

   用户输入一个url地址,查询表是否包含此url,如果存在,则返回seq的数字,

   如果不存在,则插入数据库,得到一个新增加的自增seq数字,为了缩短数字占用的字符数,我们可以把abc等字母的大小写用上。这样10个数字,26个小写字母,26个大小字母就组成了一个62进制了。比如数字10000000000(100亿)转换后就是aUKYOA,只有6位了,这样就能缩短很多的网址了。

   下面是php的进制转换代码,来源于php手册(简单吧),当然其他语言实现也是很简单的,

<?php
//十进制转到其他制
function dec2any( $num,$base=62,$index=false ) {
if (!$base ) {
$base=strlen( $index );
   }
elseif (!$index ) {
$index=substr( "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",0,$base );
   }
$out="";
for ( $t=floor( log10( $num ) /log10( $base ) ); $t>=0; $t-- ) {
$a=floor( $num/pow( $base,$t ) );
$out=$out.substr( $index,$a,1 );
$num=$num- ( $a*pow( $base,$t ) );
   }
return$out;
}

function any2dec( $num,$base=62,$index=false ) {
if (!$base ) {
$base=strlen( $index );
   }
elseif (!$index ) {
$index=substr( "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",0,$base );
   }
$out=0;
$len=strlen( $num ) -1;
for ( $t=0; $t<=$len; $t++ ) {
$out=$out+strpos( $index,substr( $num,$t,1 ) ) *pow( $base,$len-$t );
   }
return$out;
}

?>

上面只是说了下实现的原理,如果要大规模的使用,后端可以抛弃数据,用key-value数据库存储,比如ttserver,将会有很高的性能提升。

     如果改下ttserver的源代码,通过ttserver的http接口直接跳转,那么性能将会非常高,一台机器一天提供上10亿次的中专都不是问题。用两台机器就可以实现高可用了,这种服务都不怎么耗费流量的。

有名气的如:TinyURL(Twitter最先使用的), Bit.Ly(Twitter现在使用的),Is.Gd 等等,网上现在搜索一下一大把。

都知道怎么用,可它是如何工作的呢?

说起来也很简单,就是一个数据库,然后一一对应存储缩短字符和原URL。

当你要缩短一个网址时,先会去数据库看该网址有没有被存储过,如果存储过,直接返回你已经缩短的字符,比如我们常见的就4~6位;

如果没有存储,那就通过一些算法,来生成缩短字符,并和原URL一起存到数据库。

这中间会有重复的问题,那就得看算法实现了,网上目前也有很多种算法,大家有兴趣可以去找找。

生成短网址算法:

function base62($x)

{

   $show = '';

   while($x > 0) {

       $s = $x % 62;

       if ($s > 35) {

           $s = chr($s+61);             

       } elseif ($s > 9 && $s <=35) {

           $s = chr($s + 55);

       }

       $show .= $s;

       $x = floor($x/62);

   }

   return $show;     

}

function urlShort($url)

{

   $url = crc32($url);

   $result = sprintf("%u", $url);

   return base62($result);

}

echo urlShort("http://www.jaycent.com/");

PHP函数库里面,提到CURL,恐怕很多人都会翘起大拇指吧,确实,这个函数库太牛叉了

CURL其实是调用的CURL的lib,随着PHP版本的升高,curl所需的lib版本也随之提高。

关于CURL所必须的类库和安装说明,手册上有详细介绍:

XML/HTML代码

  1. Requirements  

  2.  

  3. In order to use PHP's cURL functions you need to install the libcurl package. PHP requires that you use libcurl 7.0.2-beta or higher. In PHP 4.2.3, you will need libcurl version 7.9.0 or higher. From PHP 4.3.0, you will need a libcurl version that's 7.9.8 or higher. PHP 5.0.0 requires a libcurl version 7.10.5 or greater.  

  4.  

  5. Installation  

  6.  

  7. To use PHP's cURL support you must also compile PHP --with-curl[=DIR] where DIR is the location of the directory containing the lib and include directories. In the "include" directory there should be a folder named "curl" which should contain the easy.h and curl.h files. There should be a file named libcurl.a located in the "lib" directory. Beginning with PHP 4.3.0 you can configure PHP to use cURL for URL streams --with-curlwrappers.   

  8.  

  9. Note to Win32 Users: In order to enable this module on a Windows environment, libeay32.dll and ssleay32.dll must be present in your PATH.   

  10. You don't need libcurl.dll from the cURL site.   

然后在使用的时候也很方便,只需要初始化一下,设置一下postfields或者GET啥啥的,最后exec一下就行了。关键是别忘了close.

例子代码如下:

PHP代码

  1. $ch = curl_init("http://www.example.com/");  

  2. $fp = fopen("example_homepage.txt", "w");  

  3.  

  4. curl_setopt($ch, CURLOPT_FILE, $fp);  

  5. curl_setopt($ch, CURLOPT_HEADER, 0);  

  6.  

  7. curl_exec($ch);  

  8. curl_close($ch);  

  9. fclose($fp);  

以上例子代码有点特殊,是因为他把网页内容进行了下载,同时生成一个文件。这是默认调用GET的方法。

其实,CURL更多的是用来处理POST数据、上传文件等功能

例子如下:

PHP代码

  1. <?   

  2. /*  

  3. * Author: Ron  

  4. * Released: August 4, 2007  

  5. * Description: An example of the disguise_curl() function in order to grab contents from a website while remaining fully camouflaged by using a fake user agent and fake headers.  

  6. */   

  7.  

  8. $url = 'http://www.ericgiguere.com/tools/http-header-viewer.html';   

  9.  

  10. // disguises the curl using fake headers and a fake user agent.   

  11. function disguise_curl($url)   

  12. {   

  13.  $curl = curl_init();   

  14.  

  15.  // Setup headers - I used the same headers from Firefox version 2.0.0.6   

  16.  // below was split up because php.net said the line was too long. :/   

  17.  $header[0] = "Accept: text/xml,application/xml,application/xhtml+xml,";   

  18.  $header[0] .= "text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5";   

  19.  $header[] = "Cache-Control: max-age=0";   

  20.  $header[] = "Connection: keep-alive";   

  21.  $header[] = "Keep-Alive: 300";   

  22.  $header[] = "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7";   

  23.  $header[] = "Accept-Language: en-us,en;q=0.5";   

  24.  $header[] = "Pragma: "; // browsers keep this blank.   

  25.  

  26.  curl_setopt($curl, CURLOPT_URL, $url);   

  27.  curl_setopt($curl, CURLOPT_USERAGENT, 'Googlebot/2.1 (+http://www.google.com/bot.html)');   

  28.  curl_setopt($curl, CURLOPT_HTTPHEADER, $header);   

  29.  curl_setopt($curl, CURLOPT_REFERER, 'http://www.google.com');   

  30.  curl_setopt($curl, CURLOPT_ENCODING, 'gzip,deflate');   

  31.  curl_setopt($curl, CURLOPT_AUTOREFERER, true);   

  32.  curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);   

  33.  curl_setopt($curl, CURLOPT_TIMEOUT, 10);   

  34.  

  35.  $html = curl_exec($curl); // execute the curl command   

  36.  curl_close($curl); // close the connection   

  37.  

  38.  return $html; // and finally, return $html   

  39. }   

  40.  

  41. // uses the function and displays the text off the website   

  42. $text = disguise_curl($url);   

  43. echo $text;   

  44. ?>   

上面是一个比较完整的实现。特别需要注意的是header头部的发送,最初看手册的时候,我一以为CURLOPT_HTTPHEADER所需的数组是键值对应的,即:

PHP代码

  1. $header = array('Keep-Alive'=>'300');  

现实的残酷告诉我,不应该这么用,而是象上面的例子那样,每条header为数组的一个记录。

切记切记啊

$char = $string{$position}; // where $position is the position of the character you are looking for

$string = "testing";
echo $string{2}; // prints 's'

先了解一下 Javascript 中charCodeAt的作用和用法
JavaScript charCodeAt() 方法定义和用法
charCodeAt() 方法可返回指定位置的字符的 Unicode 编码。这个返回值是 0 - 65535 之间的整数。
方法 charCodeAt() 与 charAt() 方法执行的操作相似,只不过前者返回的是位于指定位置的字符的编码,而后者返回的是字符子串。
语法
stringObject.charCodeAt(index)
参数 描述
index 必需。表示字符串中某个位置的数字,即字符在字符串中的下标。
提示和注释
注释:字符串中第一个字符的下标是 0。如果 index 是负数,或大于等于字符串的长度,则 charCodeAt() 返回 NaN。
实例
在字符串 "Hello world!" 中,我们将返回位置 1 的字符的 Unicode 编码:
<script type="text/javascript">var str="Hello world!"document.write(str.charCodeAt(1))</script>
以上代码的输出是:
101
TIY
charCodeAt()
如何使用 charCodeAt() 来获得字符串中某个具体字符的 Unicode 编码。

下面这个PHP函数可以获得字符的 Unicode码
function getUnicodeFromOneUTF8($word) {
//获取其字符的内部数组表示,所以本文件应用utf-8编码!
if (is_array( $word))
 $arr = $word;
else  
 $arr = str_split($word);
//此时,$arr应类似array(228, 189, 160)
//定义一个空字符串存储
$bin_str = '';
//转成数字再转成二进制字符串,最后联合起来。
foreach ($arr as $value)
 $bin_str .= decbin(ord($value));
//此时,$bin_str应类似111001001011110110100000,如果是汉字"你"
//正则截取
$bin_str = preg_replace('/^.{4}(.{4}).{2}(.{6}).{2}(.{6})$/','$1$2$3', $bin_str);
//此时, $bin_str应类似0100111101100000,如果是汉字"你"
return bindec($bin_str); //返回类似20320,汉字"你"
//return dechex(bindec($bin_str)); //如想返回十六进制4f60,用这句
}

 

function charAt($a, $b){
return $a{$b};
}

function charCodeAt($str, $i){
return ord(substr($str, $i, 1));
}

 

function charCodeAt($str, $i){
return ord(substr($str, $i, 1));
}


function getGTK($str) {
$hash = 5381;
$len = strlen($str);
for($i = 0; $i < $len; ++$i){
//echo getUnicodeFromOneUTF8($str{$i});
       $hash += ($hash << 5) +charCodeAt($str, $i);
   }

   return $hash & 0x7fffffff;
}

unicode_decode — Decode Unicode, convert a binary string into a Unicode string for PHP 5.3, this function will be introduced in PHP 6.

 

function unicode_decode($string) {

   $string = preg_replace_callback('#\\\\u([0-9a-f]{4})#ism',

   create_function('$matches', 'return mb_convert_encoding(pack("H*", $matches[1]), "UTF-8", "UCS-2BE");'),

   $string);

   return $string;

}

 

<?php
function unicode_encode($name)
{
    $name = iconv('UTF-8', 'UCS-2', $name);
    $len = strlen($name);
    $str = '';
    for ($i = 0; $i < $len - 1; $i = $i + 2)
    {
        $c = $name[$i];
        $c2 = $name[$i + 1];
        if (ord($c) > 0)
        {   //两个字节的文字
            $str .= '\u'.base_convert(ord($c), 10, 16).str_pad(base_convert(ord($c2), 10, 16), 2, 0, STR_PAD_LEFT);
        }
        else
        {
            $str .= $c2;
        }
    }
    return $str;
}

//将UNICODE编码后的内容进行解码
function unicode_decode($name)
{
    //转换编码,将Unicode编码转换成可以浏览的utf-8编码
    $pattern = '/([\w]+)|(\\\u([\w]{4}))/i';
    preg_match_all($pattern, $name, $matches);
    if (!empty($matches))
    {
        $name = '';
        for ($j = 0; $j < count($matches[0]); $j++)
        {
            $str = $matches[0][$j];
            if (strpos($str, '\\u') === 0)
            {
                $code = base_convert(substr($str, 2, 2), 16, 10);
                $code2 = base_convert(substr($str, 4), 16, 10);
                $c = chr($code).chr($code2);
                $c = iconv('UCS-2', 'UTF-8', $c);
                $name .= $c;
            }
            else
            {
                $name .= $str;
            }
        }
    }
    return $name;
}

uchome_ROOT/为uchome的根目录
第一步:
定位到uchome_ROOT/source/do_login.php,找到如下函数:

PHP代码
  1. //同步获取用户源  

  2. if(!$passport = getpassport($username, $password)) {  

  3.    showmessage('login_failure_please_re_login', 'do.php?ac='.$_SCONFIG['login_action']);  

  4. }  

上示函数便是登陆的第一步处理函数,再次定位:

uchome_ROOT/source/function_common.php,找到如下函数:

PHP代码
  1. //获取用户数据  

  2. function getpassport($username, $password) {  

  3.    global $_SGLOBAL, $_SC;  

  4.  

  5.    $passport = array();  

  6.    if(!@include_once S_ROOT.'./uc_client/client.php') {  

  7.        showmessage('system_error');  

  8.    }  

  9.  

  10.    $ucresult = uc_user_login($username, $password);  

  11.    if($ucresult[0] > 0) {  

  12.        $passport['uid'] = $ucresult[0];  

  13.        $passport['username'] = $ucresult[1];  

  14.        $passport['email'] = $ucresult[3];  

  15.    }  

  16.    return $passport;  

  17. }  

至此,我们可以发现现在开始和uc_client相关函数关联了.我们进入uc_client文件夹,开始分析,定位至:uchome_ROOT/uc_client/client.php

PHP代码
  1. /**

  2. * 用户登陆检查

  3. *

  4. * @param string $username  用户名/uid

  5. * @param string $password  密码

  6. * @param int $isuid        是否为uid

  7. * @param int $checkques    是否使用检查安全问答

  8. * @param int $questionid   安全提问

  9. * @param string $answer    安全提问答案

  10. * @return array (uid/status, username, password, email)

  11.    数组第一项

  12.    1  : 成功

  13.    -1 : 用户不存在,或者被删除

  14.    -2 : 密码错

  15. */  

  16. function uc_user_login($username, $password, $isuid = 0, $checkques = 0, $questionid = '', $answer = '') {  

  17.    $isuid = intval($isuid);  

  18.    //define('UC_API_FUNC', UC_CONNECT == 'mysql' ? 'uc_api_mysql' : 'uc_api_post');  

  19.    $return = call_user_func(UC_API_FUNC, 'user', 'login', array('username'=>$username, 'password'=>$password, 'isuid'=>$isuid, 'checkques'=>$checkques, 'questionid'=>$questionid, 'answer'=>$answer));  

  20.    return UC_CONNECT == 'mysql' ? $return : uc_unserialize($return);  

  21. }  

因为是mysql,故,UC_API_FUNC的值为uc_api_mysql,通过call_user_func()函数,将参数传给uc_api_mysql(),下面进入最关键的函数了:

uchome_ROOT/uc_client/client.php => uc_api_mysql()

PHP代码
  1. /**

  2. * MYSQL 方式取指定的模块和动作的数据

  3. *

  4. * @param string $model     请求的模块

  5. * @param string $action    请求的动作

  6. * @param string $args      参数(会加密的方式传送)

  7. * @return mix

  8. */  

  9.  

  10. function uc_api_mysql($model, $action, $args=array()) {  

  11.    //$model = 'user',$action= 'login',  

  12.    //$args = Array ( [username] => test2 [password] => test [isuid] => 0 [checkques] => 0 [questionid] => [answer] => )  

  13.    global $uc_controls;  

  14.    if(empty($uc_controls[$model])) {  

  15.        //UC_ROOT uc_client/  

  16.        include_once UC_ROOT.'./lib/db.class.php';  

  17.        include_once UC_ROOT.'./model/base.php';  

  18.        include_once UC_ROOT."./control/$model.php";  

  19.        eval("\$uc_controls['$model'] = new {$model}control();");  

  20.        //uc_client/control/user.php,usercontrol()类(继承至base基类)实例化  

  21.    }  

  22.    if($action{0} != '_') {  

  23.        $args = uc_addslashes($args, 1, TRUE);  

  24.        $action = 'on'.$action;//onlogin,usercontrol()中的方法,可以考虑改造此函数以实现预定功能  

  25.        $uc_controls[$model]->input = $args;//base.php,base基类的方法  

  26.        //return Array ( [0] => 3 [1] => test2 [2] => test [3] => test@12.com [4] => 0 )  

  27.          

  28.        return $uc_controls[$model]->$action($args);//返回预定数组,供调用函数分析  

  29.    } else {  

  30.        return '';  

  31.    }  

  32. }  

我们看看 usercontrol类的 onlogin()方法:

uchome_ROOT/uc_client/control/user.php

PHP代码
  1. //note public 外部接口 登陆接口  

  2. function onlogin() {  

  3.    $this->init_input();  

  4.    $isuid = $this->input('isuid');  

  5.    $username = $this->input('username');  

  6.    $password = $this->input('password');  

  7.    $checkques = $this->input('checkques');  

  8.    $questionid = $this->input('questionid');  

  9.    $answer = $this->input('answer');  

  10.    if($isuid) {  

  11.        $user = $_ENV['user']->get_user_by_uid($username);  

  12.    } else {  

  13.        $user = $_ENV['user']->get_user_by_username($username);  

  14.    }  

  15.  //这部分即可改动

  16.    $passwordmd5 = preg_match('/^\w{32}$/', $password) ? $password : md5($password);  

  17.    //note 用户名不存在  

  18.    if(empty($user)) {  

  19.        $status = -1;  

  20.    } elseif($user['password'] != md5($passwordmd5.$user['salt'])) {  

  21.        $status = -2;  

  22.    } elseif($checkques && $user['secques'] != '' && $user['secques'] != $_ENV['user']->quescrypt($questionid, $answer)) {  

  23.        $status = -3;  

  24.    } else {  

  25.        $status = $user['uid'];  

  26.    }  

  27.    $merge = $status != -1 && !$isuid && $_ENV['user']->check_mergeuser($username) ? 1 : 0;  

  28.    return array($status, $user['username'], $password, $user['email'], $merge);  

  29. }  

可以改成如下形式:

PHP代码
  1. //note public 外部接口 登陆接  

  2.    function onlogin($type='myself') {  

  3.        $this->init_input();  

  4.        $isuid = $this->input('isuid');  

  5.        $username = $this->input('username');  

  6.        $password = $this->input('password');  

  7.        $checkques = $this->input('checkques');  

  8.        $questionid = $this->input('questionid');  

  9.        $answer = $this->input('answer');  

  10.        if($isuid) {  

  11.            $user = $_ENV['user']->get_user_by_uid($username);  

  12.        } else {  

  13.            $user = $_ENV['user']->get_user_by_username($username);  

  14.        }  

  15.  

  16.        $passwordmd5 = preg_match('/^\w{32}$/', $password) ? $password : md5($password);  

  17.  

  18.        $type='myself';  

  19.        if($type=='myself')  

  20.        {  

  21.            echo '$password:'.$password.'<br>';  

  22.            $testmd5 = md5('test');//假设数据库中保持的所有的密码为test  

  23. //          print_r($passwordmd5);  

  24. //          print_r($user);  

  25.            //note 用户名不存在  

  26.              

  27.            if(emptyempty($user)) {  

  28.                $status = -1;  

  29.            } elseif($user['password'] != $passwordmd5) {  

  30.                $status = -2;  

  31.            } elseif($checkques && $user['secques'] != '' && $user['secques'] != $_ENV['user']->quescrypt($questionid, $answer)) {  

  32.                $status = -3;  

  33.            } else {  

  34.                $status = $user['uid'];  

  35.            }  

  36. //          echo '<br>$statusz:'.$status.'<br>';  

  37. //          die();  

  38.        }else{  

  39.            if(emptyempty($user)) {  

  40.                $status = -1;  

  41.            } elseif($user['password'] != md5($passwordmd5.$user['salt'])) {  

  42.                $status = -2;  

  43.            } elseif($checkques && $user['secques'] != '' && $user['secques'] != $_ENV['user']->quescrypt($questionid, $answer)) {  

  44.                $status = -3;  

  45.            } else {  

  46.                $status = $user['uid'];  

  47.            }  

  48.        }  

  49.        $merge = $status != -1 && !$isuid && $_ENV['user']->check_mergeuser($username) ? 1 : 0;  

  50.        return array($status, $user['username'], $password, $user['email'], $merge);  

  51.    }  


至此,我们可以更改uchome默认的认证方式了,如果这里更改了,以后相关的也需要作出更改,这个就留下大家自己去跟踪调试了.

tips:

uchome_ROOT/uc_client/model/user.php下还有一个check_login(),这个函数暂时没有找到调用的地方.

PHP代码
  1. function check_login($username, $password, &$user) {  

  2.    $user = $this->get_user_by_username($username);  

  3.    if(empty($user['username'])) {  

  4.        return -1;  

  5.    } elseif($user['password'] != md5(md5($password).$user['salt'])) {  

  6.        return -2;  

  7.    }  

  8.    return $user['uid'];  

  9. }  

.htaccess文件使用详解

1.1 什么是.htaccess文件从本指南中,你将可以学习到有关.htaccess文件及其功能的知识,并用以优化你的网站。尽管.htaccess 只是一个文件,但它可以更改服务器的设置,允许你做许多不同的事情,最流行的功能是您可以创建自定义的“404 error”页面。.htaccess 并不难于使用,归根结底,它只是在一个text文档中添加几条简单的指令而已。

首先你要判断主机支持它

这可能很难用简单的答案来回答。许多主机支持.htaccess,但实际上并不会特别声明,许多其他类型的主机有能力 但并不允许他们的用户使用. htaccess。一般来说,如果你的主机使用Unix或Linux系统,或任何版本的Apache网络服务器,从理论上都是支持.htaccess的,尽管你的主机服务商可能不允许你使用它。

判断你的主机是否允许.htaccess,一个标志很好的是它是否支持文件夹密码保护。为达到此功能,主机服务商需要 使用.htaccess(当然,少数情况下他们虽提供密码保护功能,但却并不允许你使用.htaccess)。如果你不确定自己的主机是否支持. htaccess,最好的办法是上传你自己的.htaccess文件看看是否有用,或者直接发送e-mail向你的主机服务商咨询。

Apache系统中的.htaccess文件(或者”分布式配置文件”提供了针对目录改变配置的方法,即,在一个特定 的文档目录中放置一个包含一个或多个指令的文件,以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过Apache的 AllowOverride指令来设置。

子目录中的指令会覆盖更高级目录或者主服务器配置文件中的指令。

.htaccess必须以ASCII模式上传,最好将其权限设置为644。

.htaccess可以做大量的事情,包括:文件夹密码保护、用户自动重定向、自定义错误页面、改变你的文件扩展名、封禁特定IP地址的用户、只允许特定IP地址的用户、禁止目录列表,以及使用其他文件作为index文件。

1.2 如何创建.httaccess文件创建.htaccess文件也许会给你带来一些困难。写文件很容易,你只需要在文字编缉器(例如:写字板)里写下适当的代码。真正困难的可能是文件的保存,因为.htaccess是一个古怪的文件名(它事实上没有文件名,只有一个由8个字母组成的扩展名),而在一些系统(如windows 3.1)中无法接受这样的文件名。在大多数的操作系统中,你需要做的是将文档保存成名为:“.htaccess” (包括引号)。如果这也不行,你需要将其先命名为其它名字(例如htaccess.txt),再将其上传到服务器上,之后直接使用FTP软件来重命名。

警告

在使用.htaccess之前,我必须给你一些警告。虽然在服务器上使用.htaccess绝对不太可能给你带来任何 麻烦(如果有些东西错了,它只是没效用罢了),但如果你使用Microsoft FrontPage Extensions,就必须特别小心。因为FrontPage Extensions本身使用了.htaccess,因此你不能编辑它并加入你自己的信息。如果确实有这方面的需要(并不推荐,但是可能),你应该先从服务器上下载.htaccess文档(如果存在),之后在前面加上你的代码。

2|.httacces文件的配置

2.1.配置.htaccess 自定义错误页
我要介绍的.htaccess的第一个应用是自定义错误页面,这将使你可以拥有自己的、个性化的错误页面(例如找不到文件时),而不是你的服务商提供的错误页或没有任何页面。这会让你的网站在出错的时候看上去更专业。你还可以利用脚本程序在发生错误的时候通知你(例如我使用Free Webmaster Help的PHP脚本程序,当找不到页面的时候自动e-mail给我)。

你所知道的任何页面错误代码(像404找不到页面),都可以通过在.htaccess文件里加入下面的文字将其变成自定义页面:

ErrorDocument errornumber /file.html

举例来说,如果我的根目录下有一个nofound.html文件,我想使用它作为404 error的页面:

ErrorDocument 404 /notfound.html

如果文件不在网站的根目录下,你只需要把路径设置为:ErrorDocument 500 /errorpages/500.html

以下是一些最常用的错误:

常用的客户端请求错误返回代码:

400 - Bad request 错误请求
401 Authorization Required需要验证
403 Forbidden禁止
404 Not Found找不到页面
405 Method Not Allowed
408 Request Timed Out
411 Content Length Required
412 Precondition Failed
413 Request Entity Too Long
414 Request URI Too Long
415 Unsupported Media Type

常见的服务器错误返回代码:

500 Internal Server Error内部服务器错误

接下来,你要做的只是创建一个错误发生时显示的文件,然后把它们和.htaccess一起上传。

用户可以利用.htaccess指定自己事先制作好的错误提醒页面。一般情况下,人们可以专门设立一个目录,例如errors放置这些页面。然后再.htaccess中,加入如下的指令:

ErrorDocument 404 /errors/notfound.html
ErrorDocument 500 /errors/internalerror.html

一条指令一行。上述第一条指令的意思是对于404,也就是没有找到所需要的文档的时候得显示页面为/errors目录下的notfound.html页面。不难看出语法格式为:

ErrorDocument 错误代码 /目录名/文件名.扩展名

如果所需要提示的信息很少的话,不必专门制作页面,直接在指令中使用HTML号了,例如下面这个例子:

ErrorDocument 401 “你没有权限访问该页面,请放弃!”

2.2.配置.htaccess 停示显示目录列表
有些时候,由于某种原因,你的目录里没有index文件,这意味着当有人在浏览器地址栏键入了该目录的路径,该目录下所有的文件都会显示出来,这会给你的网站留下安全隐患。

为避免这种情况(而不必创建一堆的新index文件),你可以在你的.htaccess文档中键入以下命令,用以阻止目录列表的显示: Options -Indexes

2.3.配置.htaccess 阻止/允许特定的IP地址某些情况下,你可能只想允许某些特定IP的用户可以访问你的网站(例如:只允许使用特定ISP的用户进入某个目录),或者想封禁某些特定的IP地址(例如:将低级用户隔离于你的信息版面外)。当然,这只在你知道你想拦截的IP地址时才有用,然而现在网上的大多数用户都使用动态IP地址,所以这并不是限制使用的常用方法。

你可以使用以下命令封禁一个IP地址:

deny from 000.000.000.000

这里的000.000.000.000是被封禁的IP地址,如果你只指明了其中的几个,则可以封禁整个网段的地址。如你输入210.10.56.,则将封禁210.10.56.0~210.10.56.255的所有IP地址。

你可以使用以下命令允许一个IP地址访问网站:

allow from 000.000.000.000

被允许的IP地址则为000.000.000.000,你可以象封禁IP地址一样封禁整个网段。

如果你想阻止所有人访问该目录,则可以使用:

deny from all

不过这并不影响脚本程序使用这个目录下的文档。

2.4.配置.htaccess 替换index文件
改变缺省的首页文件

一般情况下缺省的首页文件名有default、index等。不过,有些时候目录中没有缺省文件,而是某个特定的文件名,比如在w3sky中是 w3sky.PHP。这种情况下,要用户记住文件名来访问很麻烦。在.htaccess中可以轻易的设置新的缺省文件名:

DirectoryIndex 新的缺省文件名

也可以列出多个,顺序表明它们之间的优先级别,例如:

DirectoryIndex filename.html index.cgi index.pl default.htm

也许你不想一直使用index.htm或index.html作为目录的索引文件。举例来说,如果你的站点使用 PHP 文件,你可能会想使用 index.PHP来作为该目录的索引文档。当然也不必局限于“index”文档,如果你愿意,使用.htaccess你甚至能够设置 foofoo.balh来作为你的索引文档这些互为替换的索引文件可以排成一个列表,服务器会从左至右进行寻找,检查哪个文档在真实的目录中存在。如果一个也找不到,它将会把目录列表显示出来(除非你已经关闭了显示目录文件列表)。

DirectoryIndex index.PHP index.PHP3 messagebrd.pl index.html index.htm

2.5.配置.htaccess 重定向页面
.htaccess最有用的功能之一就是将请求重定向到同站内或站外的不同文档。这在你改变了一个文件名称,但仍然想让用户用旧地址访问到它时,变的极为有用。另一个应用(我发现的很有用的)是重定向到一个长URL,例如在我的时事通讯中,我可以使用一个很简短的URL 来指向我的会员链接。以下是一个重定向文件的例子:

Redirect /location/from/root/file.ext
http://www.w3sky.com/new/file/123.html

上述例子中,访问在root目录下的名为oldfile.html可以键入:

/oldfile.html

访问一个旧次级目录中的文件可以键入:

/old/oldfile.html

你也可以使用.htaccess重定向整个网站的目录。假如你的网站上有一个名为olddirectory的目录,并且你已经在一个新网站 http://www.w3sky.com/newdirectory/上建立了与上相同的文档,你可以将旧目录下所有的文件做一次重定向而不必一一声明:

Redirect /olddirectory http://www.w3sky.com/newdirectory

这样,任何指向到站点中/olddirectory目录的请求都将被重新指向新的站点,包括附加的额外URL信息。如果正确使用,此功能将极其强大。

我们可能对网站进行重新规划,将文档进行了迁移,或者更改了目录。这时候,来自搜索引擎或者其他网站链接过来的访问就可能出错。这种情况下,可以通过如下指令来完成旧的URL自动转向到新的地址:

Redirect /旧目录/旧文档名 新文档的地址

或者整个目录的转向:

Redirect 旧目录 新目录

3.1.密码保护的.htaccess文件尽管有各种各样的.htaccess用法,但至今最流行的也可能是最有用的做法是将其用于网站目录可靠的密码保护。尽管JavaScrip等也能做到,但只有.htaccess具有完美的安全性(即访问者必须知晓密码才可以访问目录,并且绝无“后门”可走)。

利用.htaccess将一个目录加上密码保护分两个步骤。第一步是在你的.htaccess文档里加上适当的几行代码,再将.htaccess文档放进你要保护的目录下:

AuthName “Section Name”
AuthType Basic
AuthUserFile /full/path/to/.htpasswd
Require valid-user

你可能需要根据你的网站情况修改一下上述内容中的一些部分,如用被保护部分的名字”Members Area”,替换掉“Section Name”。

/full/parth/to/.htpasswd则应该替换为指向.htpasswd文件(后面详述该文档)的完整服务器路径。如果你不知道你网站空间的完整路径,请询问一下你的系统管理员。

3.2.密码保护的.htpasswd文件
目录的密码保护比.htaccess的其他功能要麻烦些,因为你必须同时创建一个包含用户名和密码的文档,用于访问你的网站,相关信息(默认)位于一个名为.htpasswd的文档里。像.htaccess一样,.htpasswd也是一个没有文件名且具有8位扩展名的文档,可以放置在你网站里的任何地方(此时密码应加密),但建议你将其保存在网站Web根目录外,这样通过网络就无法访问到它了。

在使用.htaccess来设置目录的密码保护时,它包含了密码文件的路径。从安全考虑,有必要把.htaccess 也保护起来,不让别人看到其中的内容。虽然可以用其他方式做到这点,比如文档的权限。不过,.htaccess本身也能做到,只需加入如下的指令:

order allow,deny
deny from all

3.3.配置 .htaccess 输入用户名和密码
要利用.htaccess对某个目录下的文档设定访问用户和对应的密码,首先要做的是生成一个.htpasswd的文本文档,例如:

forge:y4E7Ec8e7EwV

这里密码经过加密,用户可以自己找些工具将密码加密成.htaccess支持的编码。该文档最好不要放在www目录下,建议放在www根目录文档之外,这样更为安全些。

有了授权用户文档,可以在.htaccess中加入如下指令了:

AuthUserFile .htpasswd的服务器目录
AuthGroupFile /dev/null (需要授权访问的目录)
AuthName EnterPassword
AuthType Basic (授权类型)

require user wsabstract (允许访问的用户,如果希望表中所有用户都允许,可以使用 require valid-user)

注,括号部分为学习时候自己添加的注释

拒绝来自某个IP的访问

如果我不想某个政府部门访问到我的站点的内容,那可以通过.htaccess中加入该部门的IP而将它们拒绝在外。

例如:
order allow,deny
deny from 210.10.56.32
deny from 219.5.45.
allow from all

第二行拒绝某个IP,第三行拒绝某个IP段,也就是219.5.45.0~219.2.45.255

想要拒绝所有人?用deny from all好了。不止用IP,也可以用域名来设定。

创建好.htpasswd文档后(可以通过文字编辑器创建),下一步是输入用于访问网站的用户名和密码,应为:

username:password

“password”的位置应该是加密过的密码。你可以通过几种方法来得到加密过的密码:一是使用一个网上提供的 permade脚本或自己写一个;另一个很不错的username/password加密服务是通过KxS网站,这里允许你输入用户名及密码,然后生成正确格式的密码。

对于多用户,你只需要在.htpasswd文档中新增同样格式的一行即可。另外还有一些免费的脚本程序可以方便地管理.htpasswd文档,可以自动新增/移除用户等。

3.4.配置.htaccess 直接访问加密网站
当你试图访问被.htaccess密码保护的目录时,你的浏览器会弹出标准的username/password对话窗口。如果你不喜欢这种方式,有些脚本程序可以允许你在页面内嵌入username/password输入框来进行认证,你也可以在浏览器的URL框内以以下方式输入用户名和密码(未加密的):
http://username:password@www.w3sky.com/directory/

3.5.利用 .htaccess 防止盗链
如果不喜欢别人在他们的网页上连接自己的图片、文档的话,也可以通过htaccess的指令来做到。

所需要的指令如下:

RewriteEngine on
RewriteCond %{ HTTP_REFERER } !^$
RewriteCond %{ HTTP_REFERER } !^http://(www.)?w3sky.com/.*$ [NC]
RewriteRule .(gif &line;jpg)$ - [F]

如果觉得让别人的页面开个天窗不好看,那可以用一张图片来代替:

RewriteEngine on
RewriteCond %{ HTTP_REFERER } !^$
RewriteCond %{ HTTP_REFERER } !^http://(www.)?w3sky.com/.*$ [NC]
RewriteRule .(gif &line;jpg)$ http://www.w3sky.com/替代图片文件名 [R,L]

3.6.利用 .htaccess进行地址转向
这种方法,就是把yourdomain.com的流量全部 301转向到www.yourdomain.com(或者反过来)。其实对于这种方法,国外有人认为对PageRank没有帮助。我觉得是因为他们看到 Google管理员工具中有一个首选域工具,可以指定Google的爬虫把 www.yourdomain.com或者yourdomain.com作为抓取和排名的首选域,转向似乎就没有必要了。但确实又有不少人证实这是有效的,反正目前还没有人说这种方法会对SEO或者pagerank有什么损害。

在.htaccess中写入:

Options +FollowSymlinks All -Indexes
rewriteEngine on
rewriteBase /
RewriteCond %{HTTP_HOST} ^domain.com$
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]

3.7.利用 .htaccess对域名中“www”的控制
强制去除3w

下面以 Wordpress 为例,其它的情况,可以自己参照解决。在你的 Wordpress 目录下通常会有一个 .htaccess 文件,如果没有,那就手动建立一个。如果你设定了 permalink 的话,.htaccess 里面的内容会有如下一坨:


RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

具体是啥意思咱就甭管它了,只管在 RewriteBase / 这行下面加上:

RewriteCond %{HTTP_HOST} ^www.yourdomain.tld$ [NC]
RewriteRule ^(.*)$ http://yourdomain.tld/$1 [R=301,L]

这样就大功告成了。当然要把 yourdomain.tld 换成你自己的域名。上面两行的意思是把 www.yourdomain.tld 这种形式改写成 yourdomain.tld, 并把访问前者的所有链接永久转向到后者。

域名前强制加上www

如果你实在是坚持要把 www 加在前面,我上面的算是白写了,表示遗憾。但,你可以。只需把上面添加的两行代码改成这样:

RewriteCond %{HTTP_HOST} ^yourdomain.tld$ [NC]
RewriteRule ^(.*)$ http://www.yourdomain.tld/$1 [R=301,L]

4.1. .htaccess 总结
.htaccess是一个站点管理员可以应用的强大工具,有更多的变化以适应不同的用途,可以节约时间及提高网站的安全性

.htaccess的特别说明

* 启用.htaccess,需要修改httpd.conf,启用AllowOverride,并可以用AllowOverride限制特定命令的使用
* 如果需要使用.htaccess以外的其他文件名,可以用AccessFileName指令来改变。例如,需要使用.config ,则可以在服务器配置文件中按以下方法配置:

AccessFileName .config

* 一般情况下,不应该使用. htaccess文件,除非你对主配置文件没有访问权限。有一种很常见的误解,认为用户认证只能通过.htaccess文件实现,其实并不是这样,把用户认证写在主配置文件中是完全可行的,而且是一种很好的方法。.htaccess文件应该被用在内容提供者需要针对特定目录改变服务器的配置而又没有 root权限的情况下。如果服务器管理员不愿意频繁修改配置,则可以允许用户通过.htaccess文件自己修改配置,尤其是ISP在同一个机器上运行了多个用户站点,而又希望用户可以自己改变配置的情况下。虽然如此,一般都应该尽可能地避免使用.htaccess文件。任何希望放在.htaccess文件中的配置,都可以放在主配置文件的段中,而且更高效。避免使用.htaccess文件有两个主要原因,即性能和安全。

在线 .htaccess文件生成器http://cooletips.de/htaccess/
能够在线生成. htaccess文件,很简单的就配置重定向,系统错误文件等。
敢想敢做敢坚持

.htaccess文件提供了针对每个目录改变配置的方法。
top
.htaccess文件*
相关模块相关指令

*core
*mod_authn_file
*mod_authz_groupfile
*mod_cgi
*mod_include
*mod_mime

*AccessFileName
*AllowOverride
*Options
*AddHandler
*SetHandler
*AuthType
*AuthName
*AuthUserFile
*AuthGroupFile
*Require

top
工作原理和使用方法*

.htaccess文件(或者”分布式配置文件”)提供了针对目录改变配置的方法,即,在一个特定的文档目录中放置一个包含一个或多个指令的文件,以作用于此目录及其所有子目录。

说明:如果需要使用.htaccess以外的其他文件名,可以用AccessFileName指令来改变。例如,需要使用.config,则可以在服务器配置文件中按以下方法配置:

AccessFileName.config

允许放在这些文件中的指令取决于AllowOverride指令,此指令按类别决定了.htaccess文件中哪些指令才是有效的。如果一个指令允许放在.htaccess文件中,则,在本手册的说明中,此指令会有一个覆盖段,其中说明了为使此指令生效而必须在 AllowOverride指令中设置的值。

例如,本手册对AddDefaultCharset指令的说明表明了,此指令可以用于.htaccess文件(见 Context一行),而Override一行是”FileInfo”,那么为使.htaccess中的此指令有效,则至少要设置 ”AllowOverrideFileInfo”。

例子:
Context:serverconfig,virtualhost,directory,.htaccess
Override:FileInfo

如果不能确定一个特定的指令是否允许用于.htaccess文件,可以查阅手册中对指令的说明,看在Context(“上下文”)行中是否有”.htaccess.”。

使用.htaccess文件的场合

一般情况下,不应该使用.htaccess文件,除非你对主服务器配置文件没有存取权限。有一种很常见的误解,认为用户认证只能通过.htaccess文件实现,但并不是这样,把用户认证写在主服务器配置中是完全可行的,而且是一种很好的方法。

在内容提供者需要针对目录改变服务器的配置而对服务器系统没有root权限时,则应该使用.htaccess文件。如果服务器管理员不愿意频繁修改配置,则可以允许用户通过.htaccess文件自己修改配置,尤其是ISP在一个机器上宿主多个用户站点,而又希望用户可以自己改变配置的情