<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>生命在于折腾</title>
	<atom:link href="http://www.xa01.cc/feed" rel="self" type="application/rss+xml" />
	<link>http://www.xa01.cc</link>
	<description>折腾不息...</description>
	<lastBuildDate>Mon, 20 Feb 2012 07:16:32 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Hadoop伪分布模式搭建</title>
		<link>http://www.xa01.cc/59.html</link>
		<comments>http://www.xa01.cc/59.html#comments</comments>
		<pubDate>Mon, 20 Feb 2012 06:45:26 +0000</pubDate>
		<dc:creator>adminjs</dc:creator>
				<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.xa01.cc/?p=59</guid>
		<description><![CDATA[1.修改源
deb http://mirrors.163.com/ubuntu/ lucid main universe restricted multiverse
deb-src http://mirrors.163.com/ubuntu/ lucid main universe restricted multiverse
deb http://mirrors.163.com/ubuntu/ lucid-security universe main multiverse restricted
deb-src http://mirrors.163.com/ubuntu/ lucid-security universe main multiverse restricted
deb http://mirrors.163.com/ubuntu/ lucid-updates universe main multiverse restricted
deb http://mirrors.163.com/ubuntu/ lucid-proposed universe main multiverse restricted
deb-src http://mirrors.163.com/ubuntu/ lucid-proposed universe main multiverse restricted
deb http://mirrors.163.com/ubuntu/ lucid-backports universe main multiverse restricted
deb-src http://mirrors.163.com/ubuntu/ lucid-backports universe main multiverse restricted
deb-src http://mirrors.163.com/ubuntu/ lucid-updates universe main multiverse restricted
deb http://archive.canonical.com/ lucid partner

2.安装JDK
apt-get install default-jdk

3.添加hadoop用户组（hadoop不允许以root身份启动）
addgroup hadoop
adduser --ingroup hadoop hduser

4.配置密钥
apt-get install ssh
切换至hduser
su - hduser
ssh-keygen -t rsa -P ""

cat $HOME/.ssh/id_rsa.pub &#62;&#62; $HOME/.ssh/authorized_keys

5.下载Hadoop
wget http://mirror.bjtu.edu.cn/apache/hadoop/common/hadoop-0.20.2/hadoop-0.20.2.tar.gz

cd /usr/local
tar xzf hadoop-0.20.2.tar.gz
mv hadoop-0.20.2 hadoop
chown -R hduser:hadoop hadoop

6.配置Hadoop

修改/home/hduser/.bashrc
# Set Hadoop-related environment variables
export HADOOP_HOME=/usr/local/hadoop

# Set JAVA_HOME (we will also configure JAVA_HOME directly for Hadoop later on)
export JAVA_HOME=/usr/lib/jvm/java-6-openjdk

&#160;

7.修改Hadoop配置文件

----------------------------------------------
/usr/local/hadoop/conf/hadoop-env.sh
# export JAVA_HOME=/usr/lib/j2sdk1.5-sunto
修改为
export JAVA_HOME=/usr/lib/jvm/java-6-sun
-----------------------------------------------

------------conf/core-site.xml-----------------
&#60;!-- In: conf/core-site.xml --&#62;
&#60;property&#62;
&#60;name&#62;hadoop.tmp.dir&#60;/name&#62;
&#60;value&#62;/app/hadoop/tmp&#60;/value&#62;
&#60;description&#62;A base for other temporary directories.&#60;/description&#62;
&#60;/property&#62;

&#60;property&#62;
&#60;name&#62;fs.default.name&#60;/name&#62;
&#60;value&#62;hdfs://localhost:54310&#60;/value&#62;
&#60;description&#62;The name of the default file system. A URI whose
scheme and authority determine the FileSystem implementation. The
uri's scheme determines the config property (fs.SCHEME.impl) naming
the FileSystem implementation class. The uri's authority is used to
determine the host, port, etc. for a filesystem.&#60;/description&#62;
&#60;/property&#62;
-------------------------------------------------
------------conf/mapred-site.xml-----------------

&#60;!-- In: conf/mapred-site.xml --&#62;
&#60;property&#62;
&#60;name&#62;mapred.job.tracker&#60;/name&#62;
&#60;value&#62;localhost:54311&#60;/value&#62;
&#60;description&#62;The host and port that the MapReduce job tracker runs
at. If "local", then jobs are run in-process as a single map
and reduce task.
&#60;/description&#62;
&#60;/property&#62;
-----------------------------------------------------
--------------------conf/hdfs-site.xml---------------
&#60;!-- In: conf/hdfs-site.xml --&#62;
&#60;property&#62;
&#60;name&#62;dfs.replication&#60;/name&#62;
&#60;value&#62;1&#60;/value&#62;
&#60;description&#62;Default block replication.
The actual number of replications can be specified when the file is created.
The default is used if replication is not specified in create time.
&#60;/description&#62;
&#60;/property&#62;
-----------------------------------------------------
8.建立hadoop工作目录
mkdir -p /app/hadoop/tmp
sudo chown hduser:hadoop /app/hadoop/tmp

9.启动Hadoop
格式化工作目录
/usr/local/hadoop/bin/hadoop namenode -format

10/05/08 16:59:56 INFO namenode.NameNode: STARTUP_MSG:
/************************************************************
STARTUP_MSG: Starting NameNode
STARTUP_MSG: host = ubuntu/127.0.1.1
STARTUP_MSG: args = [-format]
STARTUP_MSG: version = 0.20.2
STARTUP_MSG: build = https://svn.apache.org/repos/asf/hadoop/common/branches/branch-0.20 -r 911707; compiled by 'chrisdo' on Fri Feb 19 08:07:34 UTC 2010
************************************************************/
10/05/08 16:59:56 INFO namenode.FSNamesystem: fsOwner=hduser,hadoop
10/05/08 16:59:56 INFO namenode.FSNamesystem: supergroup=supergroup
10/05/08 16:59:56 INFO namenode.FSNamesystem: isPermissionEnabled=true
10/05/08 16:59:56 INFO common.Storage: Image file of size 96 saved in 0 seconds.
10/05/08 16:59:57 INFO common.Storage: Storage directory .../hadoop-hduser/dfs/name has been successfully formatted.
10/05/08 16:59:57 INFO namenode.NameNode: SHUTDOWN_MSG:
/************************************************************
SHUTDOWN_MSG: Shutting down NameNode at ubuntu/127.0.1.1
************************************************************/
如果看到以上提示，说明已经格式化成功

关闭安全模式
hadoop dfsadmin -safemode leave

启动Hadoop
/usr/local/hadoop/bin/start-all.sh

执行jps
2287 TaskTracker
2149 JobTracker
1938 DataNode
2085 SecondaryNameNode
2349 Jps
1788 NameNode
如果看到以上提示，即启动成功
关闭Hadoop执行
/usr/local/hadoop/bin/stop-all.sh

伪分布安装完成

10.Hadoop文件操作

查看工作目录
/usr/local/hadoop/bin/hadoop dfs -ls /

Found 1 items
drwxr-xr-x - hduser supergroup 0 2012-02-16 14:33 /app
上传文件

/usr/local/hadoop/bin/hadoop fs -put /usr/local/hadoop/README.txt /
hduser@master:~$ /usr/local/hadoop/bin/hadoop dfs -ls /
Found 2 items
-rw-r--r-- 1 hduser supergroup 1366 2012-02-20 14:45 /README.txt
drwxr-xr-x - hduser supergroup 0 2012-02-16 14:33 /app
hduser@master:~$ /usr/local/hadoop/bin/hadoop fs -put /usr/local/hadoop/README.txt

删除文件

hduser@master:~$ /usr/local/hadoop/bin/hadoop dfs -rmr /README.txt
Deleted hdfs://master:54310/README.txt

&#160;]]></description>
		<wfw:commentRss>http://www.xa01.cc/59.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mysqlhotcopy 备份方法</title>
		<link>http://www.xa01.cc/57.html</link>
		<comments>http://www.xa01.cc/57.html#comments</comments>
		<pubDate>Sun, 29 Jan 2012 03:47:26 +0000</pubDate>
		<dc:creator>afoolfox</dc:creator>
				<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://www.xa01.cc/?p=57</guid>
		<description><![CDATA[<div>

Mysqlhotcopy 是一个 PERL 程序。它使用 LOCK TABLES、FLUSH   TABLES 和 cp 或 scp  来快速备 份数据库。它是备份数据库或单个表的最快的途径，但它只能运行在数据库文件(包括数据表定义文件、数 据文件、索引文件)所在的机器上。

mysqlhotcopy 只能用于备份 MyISAM，并且只能运行在 类 Unix 和 NetWare 系统上。

mysqlhotcopy 支持一次性拷贝多个数据库，同时还支持正则表达。

<strong>msqlhotcopy 和 mysqldump 对比：</strong>

1、前者是文件意义上的 COPY，后者是一个数据库端的 SQL 语句集合。

2、前者只能运行在数据库目录所在的机器上，后者可以用在远程客户端。

3、相同的地方都是在线执行 LOCK TABLES 以及 UNLOCK TABLES

4、前者恢复只需要 COPY 备份文件到源目录覆盖即可，后者需要倒入 SQL 文件到原来库中。(source 或 者\.或者 mysql &#60; 备份文件)。

5、前者只适用于 MyISAM 引擎，而后则则可同时使用于 MyISAM 引擎和 InodDB 引擎.

6、前者在使用前必须安装 perl-DBD-mysql 包,而后者则不需要.

<strong>试验环境：</strong>

虚拟机操作系统：Centos 5.5

数据库版本：mysql 5.1.49

perl-DBD-mysql-4.014   （Mysqlhotcopy 需要有 perl-dbd 模块的支持）

mysql 数据库目录：/var/lib/mysql mysql 数据库备份路径：/backup/mysql

1、设置/etc/my.cnf,重启 mysqld 服务，之后使用 msqlhotcopy 就不用输入用户密码

[mysqlhotcopy] interactive-timeout user=root password=123456 port=3306

2、备份方法

# mysqlhotcopy mysqldb_name /backup

</div>
<div>

// 备份 mysql 整个数据库

# mysqlhotcopy -u root -p 123456 mysql /backup/mysql

// 同时备份 mysql 和 test1 两个数据库

# mysqlhotcopy -u root -p 123456 mysql test1 /backup/mysql

// 备份 mysql 数据库里的 user 表，支持正则表达式

# mysqlhotcopy -u root -p 123456 mysql./user*/ /backup/mysql

3、备份查询

可以将每次的备份写入数据库，日后查询备份记录.

// 创建 hotcopy 数据库并建立表格 mysql&#62; create database hotcopy; mysql&#62; use hotcopy

mysql&#62; create table checkpoint(time_stamp timestamp not null,src varchar(32),dest varchar(60), msg varchar(255));

mysql&#62; select * from checkpoint;

+---------------------+-------+------------+-----------+

&#124; time_stamp                 &#124; src     &#124; dest            &#124; msg            &#124;

+---------------------+-------+------------+-----------+

&#124; 2010-07-30 14:11:45 &#124; mysql &#124; /tmp/mysql &#124; Succeeded &#124;

&#124; 2010-07-30 14:12:37 &#124; test1 &#124; /tmp/test1 &#124; Succeeded &#124;

+---------------------+-------+------------+-----------+

2 rows in set (0.00 sec)

</div>
<div>

4、恢复方法

// 复制备份的数据库 test 到相应目录，注意目录的权限。

# /bin/cp -rf /backup/mysql/test/ /var/lib/mysql/

5、选项解释

// 显示帮助消息并退出。

--help

// 如果目标存在不放弃(加上一个_old 后缀重新命名它)。

--allowold

// 不要重命名目标目录（如果存在）;新的备份自动覆盖原来的，可以实现增量备份。

--addtodest

// 在指定的 db_name.tbl_name 插入检查点条目。

--checkpoint=db_name.tbl_name

// 启用调试输出。

--debug

// 报告动作而不执行它们。

--dryrun，-n

// 所有表锁定后刷新日志。

--flushlog

// 完成后不删除以前(重新命名的)的目标。

--keepold

// 复制方法(cp 或 scp)。

-- method=command

</div>
<div>

// 备份中不包括全部索引文件。这样使备份更小、更快。可以在以后用 myisamchk -rq 重新构建索引。

--noindices

// 当连接服务器时使用的密码。请注意该选项的密码值是不可选的，不象其它 MySQL 程序。

--password=password，-p password

// 当连接本地服务器时使用的 TCP/IP 端口号。

--port=port_num，-P port_num

// 除了出现错误时保持沉默。

--quiet，-q

// 复制所有数据库名匹配给出的正则表达式的数据库。

--regexp=expr

// 用于连接的 Unix 套接字文件。

--socket=path，-S path

// 所复制的数据库名的后缀。

--suffix=str

// 临时目录(代替/tmp)。

--tmpdir=path

// 当连接服务器时使用的 MySQL 用户名.要想执行 mysqlhotcopy，你必须可以访问备份的表文件，具有

那些表的 SELECT 权限和 RELOAD 权限(以便能够执行 FLUSH TABLES).

--user=user_name，-u user_name

6、备份脚本

1）建立数据库自动备份脚本

# vi mysql-backup.sh

</div>
<div>

#！/bin/bash

PATH=/usr/local/sbin:/usr/bin:/bin

# The Directory of Backup

BACKDIR=/backup/mysql

# The Password of MySQL ROOTPASS=123456

# Remake the Directory of Backup rm -rf $BACKDIR

mkdir -p $BACKDIR

# Get the Name of Database

DBLIST=`ls -p /var/lib/mysql &#124; grep / &#124; tr -d /`

# Backup with Database for dbname in $DBLIST do

mysqlhotcopy $dbname -u root -p $ROOTPASS $BACKDIR &#124; logger -t mysqlhotcopy done

2）测试脚本运行

// 给脚本增加执行权限

# chmod 700 mysql-backup.sh

// 运行脚本

# ./mysql-backup.sh

// 查看备份是否成功

# ll /backup/mysql

// 设置备份脚本每天自动运行

# crontab –e

// 在文本里添加下面一行

00 03 * * * /root/mysql-backup.sh

// 查看作业情况

</div>
# crontab -l

00 03 * * * /root/mysql-backup.sh]]></description>
		<wfw:commentRss>http://www.xa01.cc/57.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Web开发中需要了解的东西</title>
		<link>http://www.xa01.cc/50.html</link>
		<comments>http://www.xa01.cc/50.html#comments</comments>
		<pubDate>Wed, 18 Jan 2012 08:11:56 +0000</pubDate>
		<dc:creator>lv</dc:creator>
				<category><![CDATA[感悟]]></category>

		<guid isPermaLink="false">http://www.xa01.cc/?p=50</guid>
		<description><![CDATA[在StackExchange上有人问了这样一个问题：<a onclick="pageTracker._trackPageview('/outgoing/programmers.stackexchange.com/questions/46716/what-should-every-programmer-know-about-web-development?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://programmers.stackexchange.com/questions/46716/what-should-every-programmer-know-about-web-development" target="_blank">What should every programmer know about web development?</a>（关于Web开发，什么是所有程序员需要知道的？）里面给出的答案非常不错，所以，我翻译转载过来。 顺便说一下，StackExchange真是非常好，大家可以对同一个答案做贡献和修订，看看这个问题的<a onclick="pageTracker._trackPageview('/outgoing/programmers.stackexchange.com/posts/46760/revisions?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://programmers.stackexchange.com/posts/46760/revisions" target="_blank">修订过程</a>你就知道了——专业的问答网站应该怎么去做。这就是我在这篇文章中也说过<a title="腾讯，竞争力 和 用户体验" href="http://coolshell.cn/articles/5901.html" target="_blank">真正的用户体验是什么样的</a>。

好了，下面是正文（我对原文做了一些批注，也许不对或有误导，请大家指正）

下面的这些东西可能对于大多数人并不陌生，但是可能会有些东西你以前并没有看过，或是没有完全搞懂，甚至都没有听说过。（陈皓注：我相信当你看完这个列表后，你会觉得对于我国的Web开发有点弱了，还是那句话，表面上的东西永远是肤浅的）
<h4><strong>接口和用户体验</strong></h4>
<ul>
	<li>小心浏览器的实现标准上的不一致，确信让你的网站能够适当地跨浏览器。至少，你的网站需要测试一下下面的浏览器：
<ul>
	<li>最新的 <a onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Gecko_28layout_engine_29?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://en.wikipedia.org/wiki/Gecko_%28layout_engine%29" rel="nofollow">Gecko</a> 引擎 (<a onclick="pageTracker._trackPageview('/outgoing/firefox.com/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://firefox.com/" rel="nofollow">Firefox</a>)，</li>
	<li>一个 Webkit 引擎 (<a onclick="pageTracker._trackPageview('/outgoing/www.apple.com/safari/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.apple.com/safari/" rel="nofollow">Safari</a>, <a onclick="pageTracker._trackPageview('/outgoing/www.google.com/chrome?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.google.com/chrome" rel="nofollow">Chrome</a>, 或是其它的移动设备上的浏览器)</li>
	<li> <a onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Internet_Explorer?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://en.wikipedia.org/wiki/Internet_Explorer" rel="nofollow">IE 浏览器</a> (测试IE的兼容性你可以使用微软IE的 <a onclick="pageTracker._trackPageview('/outgoing/www.microsoft.com/Downloads/details.aspx?FamilyID=21eabb90-958f-4b64-b5f1-73d0a413c8ef_amp_displaylang=en&#38;referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.microsoft.com/Downloads/details.aspx?FamilyID=21eabb90-958f-4b64-b5f1-73d0a413c8ef&#38;displaylang=en" rel="nofollow">Application Compatibility VPC Images</a>)</li>
	<li> <a onclick="pageTracker._trackPageview('/outgoing/www.opera.com/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.opera.com/" rel="nofollow">Opera</a> 浏览器。</li>
</ul>
</li>
</ul>
最后，你可以使用一下<a onclick="pageTracker._trackPageview('/outgoing/www.browsershots.org/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.browsershots.org/" rel="nofollow">这个工具</a> 来看看你的网页在不同的浏览器下是怎么被显示出来的（陈皓注：这个工具就是以前本站介绍过的<a title="如何检查网页浏览器的兼容性" href="http://coolshell.cn/articles/757.html" target="_blank">在不同浏览器和平台上检查你的网站的兼容性</a>）
<ul>
	<li>多考虑一下人们是怎么来访问你的网站而不是那些主流的浏览器：手机，读屏软件和搜索引擎，例如：一些Accessibility的东西： <a onclick="pageTracker._trackPageview('/outgoing/www.w3.org/WAI/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.w3.org/WAI/" rel="nofollow">WAI</a> 和  <a onclick="pageTracker._trackPageview('/outgoing/www.section508.gov/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.section508.gov/" rel="nofollow">Section508</a>, 移动设备开发：<a onclick="pageTracker._trackPageview('/outgoing/mobiforge.com/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://mobiforge.com/" rel="nofollow">MobiForge</a>.</li>
</ul>
<ul>
	<li>部署Staging：怎么部署网站的更新而不会影响用户的访问。 <a onclick="pageTracker._trackPageview('/outgoing/programmers.stackexchange.com/questions/46716/what-should-a-developer-know-before-building-a-public-web-site/46738_46738?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://programmers.stackexchange.com/questions/46716/what-should-a-developer-know-before-building-a-public-web-site/46738#46738">Ed Lucas的答案</a> 可以让你了解一些（陈皓注：Ed说了一些如版本控制，自动化build，备份，回滚等机制）。</li>
</ul>
<ul>
	<li>千万不要直接给用户显示不友好的错误信息。</li>
</ul>
<div> </div>
<ul>
	<li>千万不要把用户的邮件地址以明文显示出来，这样会被爬虫爬走并被让用户的邮箱被垃圾邮件搞死。</li>
</ul>
<ul>
	<li>为用户的链接加上 <code>rel="nofollow"</code> 的属性以 <a onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Nofollow?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://en.wikipedia.org/wiki/Nofollow" rel="nofollow">避免垃圾网站的干扰</a>。（陈皓注：<strong>nofollow</strong>是HTML的一个属性，用于通知搜索引擎“这个链接所指向的网页非我所能控制，对其内容不予置评”，或者简单地说，该链接不是对目标网站或网页的“投票”，这样搜索引擎不会再访问这个链接。这个是用来减少一些特定垃圾页面对原网站的影响，从而可以改善搜索结果的质量，并且防止垃圾链接的蔓延。）</li>
</ul>
<ul>
	<li><a onclick="pageTracker._trackPageview('/outgoing/www.codinghorror.com/blog/archives/001228.html?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.codinghorror.com/blog/archives/001228.html" rel="nofollow">为网站建立一些的限制</a> - 这个属于安全性的范畴。（陈皓注：比如你在Google注册邮箱时，你一口气注册超过两个以上的邮箱，gmail要求给你发短信或是给你打电话认证，比如Discuz论坛的会限制你发贴或是搜索的间隔时间等等，更多的网站会用CAPTCHA来确认是人为的操作。 这些限制都是为了防止垃圾和恶意攻击）</li>
</ul>
<ul>
	<li>学习如何做 <a onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Progressive_enhancement?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://en.wikipedia.org/wiki/Progressive_enhancement" rel="nofollow">Progressive Enhancement</a>. （陈皓注：<a onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Progressive_enhancement?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://en.wikipedia.org/wiki/Progressive_enhancement" rel="nofollow">Progressive Enhancement</a>是一个Web Design的理念，如：1）基础的内容和功能应该可以被所有的浏览器存取，2）页面布局的应该使用外部的CSS链接，3）Javascript也应该是外部链接还应该是 <a title="Unobtrusive JavaScript" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Unobtrusive_JavaScript?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://en.wikipedia.org/wiki/Unobtrusive_JavaScript">unobtrusive</a> 的，4）应该让用户可以设置他们的偏好）</li>
</ul>
<ul>
	<li>如果POST成功，要<a onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Post/Redirect/Get?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://en.wikipedia.org/wiki/Post/Redirect/Get" rel="nofollow">在POST方法后重定向网址</a>，这样可以阻止用户通过刷新页面重复提交。</li>
</ul>
<ul>
	<li>严重关注Accessibility。因为这是<a onclick="pageTracker._trackPageview('/outgoing/www.section508.gov/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.section508.gov/" target="_blank">法律上的需求</a>（陈皓注：Section 508是美国的508法案，其是美国劳工复健法的改进，它是一部联邦法律，这个法律要求所有技术要考虑到残障人士的应用，如果某个大众信息传播网站，如果某些用户群体（如残疾人）浏览该网站获取信息时，如果他们无法正常获得所期望的信息（如无法正常浏览），那可以依据相关法规，可以对该网站依法起诉）。 <a onclick="pageTracker._trackPageview('/outgoing/www.w3.org/WAI/intro/aria?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.w3.org/WAI/intro/aria" rel="nofollow">WAI-ARIA</a> 为这方面的事提供很不错的资源.</li>
</ul>
<h4><strong>安全</strong></h4>
<ul>
	<li>在网上有很多关于安全的文章，但是 <a onclick="pageTracker._trackPageview('/outgoing/www.owasp.org/index.php/Category_3aOWASP_Guide_Project?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.owasp.org/index.php/Category%3aOWASP_Guide_Project" rel="nofollow">OWASP 开发指导</a> 涵盖了几乎所有关于Web站点安全的东西。（陈皓注：OWASP(开放Web应用安全项目- Open Web Application Security Project)是一个开放的非营利性组织，目前全球有130个分会近万名会员，其主要目标是研议协助解决Web软体安全之标准、工具与技术文件，长期 致力于协助政府或企业了解并改善网页应用程式与网页服务的安全性。OWASP被视为Web应用安全领域的权威参考。2009年下列发布的美国国家和国际立法、标准、准则、委员会和行业实务守则参考引用了OWASP。美国联邦贸易委员会(FTC)强烈建议所有企业需遵循OWASP十大WEB弱点防护守则）</li>
</ul>
<ul>
	<li>了解什么是 <a onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/SQL_injection?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://en.wikipedia.org/wiki/SQL_injection" rel="nofollow">SQL 注入攻击</a> 并知道怎么阻止这种攻击。</li>
</ul>
<ul>
	<li>永远不要相信用户的输入（包括Cookies，因为那也是用户的输入）</li>
</ul>
<ul>
	<li>对用户的口令进行Hash，并使用salt，以防止Rainbow 攻击（陈皓注：Hash算法可用MD5或SHA1等，对口令使用salt的意思是，user 在设定密码时，system 产生另外一个random string(salt)。在datbase 存的​​是与salt + passwd 产的md5sum 及salt。 当要验证密码时就把user 输入的string 加上使用者的salt，产生md5s​​um 来比对。 理论上用salt 可以大幅度让密码更难破解，相同的密码除非刚好salt 相同，最后​​存在database 上的内容是不一样的。google一下md5+salt你可以看到很多文章。关于<a onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Rainbow_table?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://en.wikipedia.org/wiki/Rainbow_table" target="_blank">Rainbow 攻击</a>，其意思是很像密码字典表，但不同的是，Rainbow Table存的是已经被Hash过的密码了，而且其查找密码的速度更快，这样可以让攻击非常快）。使用慢一点的Hash算法来保存口令，如 bcrypt (被时间检证过了) 或是 scrypt (更强，但是也更新一些) (<a onclick="pageTracker._trackPageview('/outgoing/www.tarsnap.com/scrypt.html?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.tarsnap.com/scrypt.html" rel="nofollow">1</a>, <a onclick="pageTracker._trackPageview('/outgoing/it.slashdot.org/comments.pl?sid=1987632_amp_cid=35149842&#38;referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://it.slashdot.org/comments.pl?sid=1987632&#38;cid=35149842" rel="nofollow">2</a>)。你可以阅读一下 <a onclick="pageTracker._trackPageview('/outgoing/codahale.com/how-to-safely-store-a-password/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://codahale.com/how-to-safely-store-a-password/" rel="nofollow">How To Safely Store A Password</a>（陈皓注：酷壳以前曾介绍过<a title="如何防范密码被破解" href="http://coolshell.cn/articles/2078.html" target="_blank">bcrypt这个算法</a>，这里，我更建议我们应该让用户输入比较强的口令，比如Apple ID注册的过程需要用户输入超过8位，需要有大小写和数字的口令，或是做出类似于<a title="另类UX让你输入强口令" href="http://coolshell.cn/articles/3877.html" target="_blank">这样的用户体验的东西</a>）。</li>
</ul>
<ul>
	<li><a onclick="pageTracker._trackPageview('/outgoing/stackoverflow.com/questions/1581610/how-can-i-store-my-users-passwords-safely/1581919_1581919?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://stackoverflow.com/questions/1581610/how-can-i-store-my-users-passwords-safely/1581919#1581919">不要试图自己去发明或创造一个自己的fancy的认证系统</a>，你可能会忽略到一些不容易让你查觉的东西而导致你的站点被hack了。（陈皓注：我在<a title="如何设计“找回用户帐号”功能" href="http://coolshell.cn/articles/5987.html" target="_blank">腾讯那坑爹的申诉系统</a>中说过这个事了，我说过这句话——“真正的安全系统是协同整个社会的安全系统做出来的一道安全长城，而不是什么都要自己搞”，当然，很遗憾不是所有的人都能看懂这个事，包括一些资深的人）</li>
</ul>
<ul>
	<li>了解 <a onclick="pageTracker._trackPageview('/outgoing/www.pcisecuritystandards.org/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="https://www.pcisecuritystandards.org/" rel="nofollow">处理信用卡的一些规则 </a>. (<a onclick="pageTracker._trackPageview('/outgoing/stackoverflow.com/questions/51094/payment-processors-what-do-i-need-to-know-if-i-want-to-accept-credit-cards-on-m?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://stackoverflow.com/questions/51094/payment-processors-what-do-i-need-to-know-if-i-want-to-accept-credit-cards-on-m">这里也有一个问题你可以查看一下</a>) （陈皓注：有两上vendor可以帮助你，一个是 <a onclick="pageTracker._trackPageview('/outgoing/www.authorize.net/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.authorize.net/" rel="nofollow">Authorize.Net</a> 另一个是 <a onclick="pageTracker._trackPageview('/outgoing/www.paypal.com/cgi-bin/webscr?cmd=_payflow-pro-overview-outside&#38;referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="https://www.paypal.com/cgi-bin/webscr?cmd=_payflow-pro-overview-outside" rel="nofollow">PayFlow Pro</a>）</li>
</ul>
<ul>
	<li>使用 <a onclick="pageTracker._trackPageview('/outgoing/www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt" rel="nofollow">SSL</a>/<a onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Https?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://en.wikipedia.org/wiki/Https" rel="nofollow">HTTPS</a> 来加密传输登录页面或是任可有敏感信息的页面，比如信用卡号等。</li>
</ul>
<ul>
	<li>知道如何对付session 劫持。（陈皓注：请参看wikipedia的这<a onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Session_hijacking?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://en.wikipedia.org/wiki/Session_hijacking" target="_blank">Session Hijacking</a>，）</li>
</ul>
<ul>
	<li>避免 <a onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Cross-site_scripting?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://en.wikipedia.org/wiki/Cross-site_scripting" rel="nofollow">跨站脚本攻击</a>(XSS)。（陈皓注：参看酷壳站前几天发的《<a title="新浪微博的XSS攻击" href="http://coolshell.cn/articles/4914.html" target="_blank">新浪微博的XSS攻击事件</a>》）</li>
</ul>
<ul>
	<li>避免 <a onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Cross-site_request_forgery?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://en.wikipedia.org/wiki/Cross-site_request_forgery" rel="nofollow">跨站</a><a onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Cross-site_request_forgery?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://en.wikipedia.org/wiki/Cross-site_request_forgery" rel="nofollow">伪造</a><a onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Cross-site_request_forgery?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://en.wikipedia.org/wiki/Cross-site_request_forgery" rel="nofollow">请求攻击 cross site request forgeries</a> (XSRF).</li>
</ul>
<ul>
	<li>保持你的系统里的所有软件更新到最新的patch。</li>
</ul>
<ul>
	<li>确保你的数据库连接是安全的。</li>
</ul>
<ul>
	<li>确保你能了解最新的攻击技术，以及你系统的脆弱处。</li>
</ul>
<ul>
	<li>请读一下 <a onclick="pageTracker._trackPageview('/outgoing/code.google.com/p/browsersec/wiki/Main?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://code.google.com/p/browsersec/wiki/Main" rel="nofollow">The Google Browser Security Handbook</a>.</li>
</ul>
<ul>
	<li>请读一下 <a onclick="pageTracker._trackPageview('/outgoing/rads.stackoverflow.com/amzn/click/0470170778?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://rads.stackoverflow.com/amzn/click/0470170778" rel="nofollow">The Web Application Hacker’s Handbook</a>.</li>
</ul>
<ul>
	<li>（陈皓注：之前本站的“<a title="一些文章资源和趣闻" href="http://coolshell.cn/articles/5537.html" target="_blank">一些资源</a>”提到过<a onclick="pageTracker._trackPageview('/outgoing/wiki.mozilla.org/WebAppSec/Secure_Coding_Guidelines?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="https://wiki.mozilla.org/WebAppSec/Secure_Coding_Guidelines" target="_blank">Mozilla的安全编程规范</a>，还有Ruby on Rails的<a onclick="pageTracker._trackPageview('/outgoing/guides.rubyonrails.org/security.html?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://guides.rubyonrails.org/security.html" target="_blank">Web安全的开发教程</a>）</li>
</ul>
<h4><strong>性能</strong></h4>
<ul>
	<li>只要需要，请实现cache机制，了解并合理地使用 <a onclick="pageTracker._trackPageview('/outgoing/www.mnot.net/cache_docs/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.mnot.net/cache_docs/" rel="nofollow">HTTP caching</a> 以及 <a onclick="pageTracker._trackPageview('/outgoing/www.w3.org/TR/html5/offline.html?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.w3.org/TR/html5/offline.html" rel="nofollow">HTML5 Manifest</a>.</li>
</ul>
<ul>
	<li>优化页面 —— 不要使用20KB图片来平铺网页背景。（陈皓注：还有很多网页页面优化性的文章，你可以STFG – Search The Fucking Google一下。如果你要调试的话，你可以使用firebug或是chrome内置的开发人员的工具来查看网页装载的性能）</li>
	<li>学习如何 <a title="gzip content" onclick="pageTracker._trackPageview('/outgoing/developer.yahoo.com/performance/rules.html_gzip?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://developer.yahoo.com/performance/rules.html#gzip" rel="nofollow">gzip/deflate 网页</a> (<a onclick="pageTracker._trackPageview('/outgoing/stackoverflow.com/questions/1574168/gzip-vs-deflate-zlib-revisited?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://stackoverflow.com/questions/1574168/gzip-vs-deflate-zlib-revisited">deflate 更好</a>).</li>
</ul>
<ul>
	<li>把多个CSS文件和Javascript文件合并成一个，这样可以减少浏览器的网络连数，并且使用gzip压缩被反复用到的文件。</li>
</ul>
<ul>
	<li>学习一下 <a onclick="pageTracker._trackPageview('/outgoing/developer.yahoo.com/performance/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://developer.yahoo.com/performance/" rel="nofollow">Yahoo Exceptional Performance</a> 这个网站上的东西，上面有很多非常不错的改善前端性能的指导，以及 <a onclick="pageTracker._trackPageview('/outgoing/developer.yahoo.com/yslow/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://developer.yahoo.com/yslow/" rel="nofollow">YSlow</a> 这个工具。 <a onclick="pageTracker._trackPageview('/outgoing/code.google.com/speed/page-speed/docs/rules_intro.html?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://code.google.com/speed/page-speed/docs/rules_intro.html" rel="nofollow">Google page speed</a> 是另一个用来做性能采样的工具。这两个工具都需要安装 <a onclick="pageTracker._trackPageview('/outgoing/getfirebug.com/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://getfirebug.com/" rel="nofollow">Firebug</a> 。</li>
</ul>
<ul>
	<li>为那些小的图片使用 <a onclick="pageTracker._trackPageview('/outgoing/alistapart.com/articles/sprites?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://alistapart.com/articles/sprites" rel="nofollow">CSS Image Sprites</a>，就像工具条一样。 (参看 “最小化 HTTP 请求” ) （陈皓注：把所有的小图片合并成一个图片，然后用CSS把显示其中的一块，这样，这些小图片只用传输一次，酷壳的Wordpress样式的那个RSS订阅列表中的小图标就是这样做的）</li>
</ul>
<ul>
	<li>繁忙的网络应该考虑<a onclick="pageTracker._trackPageview('/outgoing/developer.yahoo.com/performance/rules.html_split?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://developer.yahoo.com/performance/rules.html#split" target="_blank">把网页的内容分开存放</a>在不同的域名下。（陈皓注：比如有专门的图片服务器——图片相当耗带宽，或是专门的Ajax服务器）</li>
</ul>
<ul>
	<li>静态网页 (如，图片，CSS，JavaScript，以及一些不需要访问cookies的网页) 应该放在一个<a onclick="pageTracker._trackPageview('/outgoing/blog.stackoverflow.com/2009/08/a-few-speed-improvements/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://blog.stackoverflow.com/2009/08/a-few-speed-improvements/" target="_blank">不使用cookies</a>的独立的域名下，因为所有在同一个域名或子域名下的cookie会被这个域名下的请求一同发送。另一个好的选择是使用 Content Delivery Network (CDN).</li>
</ul>
<ul>
	<li>使用单个页面的HTTP请求数最小化。</li>
</ul>
<ul>
	<li>为Javascript使用 <a onclick="pageTracker._trackPageview('/outgoing/code.google.com/closure/compiler/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://code.google.com/closure/compiler/" rel="nofollow">Google Closure Compiler</a> 或是 <a onclick="pageTracker._trackPageview('/outgoing/developer.yahoo.com/yui/compressor/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://developer.yahoo.com/yui/compressor/" rel="nofollow">其它压缩工具</a>（陈皓注：压缩Javascript代码可以让你的页面减少网络传输从而可以得到很快的喧染。注意，并不是所有的工具都可以正确压缩Javascript的，Google的这个工具甚至还可以帮你优化你的代码）</li>
</ul>
<ul>
	<li>确认你的网站有一个 <code>favicon.ico</code> 文件放在网站的根下，如 <code>/favicon.ico</code>. <a onclick="pageTracker._trackPageview('/outgoing/mathiasbynens.be/notes/rel-shortcut-icon?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://mathiasbynens.be/notes/rel-shortcut-icon" rel="nofollow">浏览器会自动请求这个文件</a>，就算这个图标文件没有在你的网页中明显说明，浏览器也会请求。如果你没有这个文件，就会出大量的404错误，这会消耗你的服务器带宽。（陈皓注：服务器返回404页面会比这个ico文件可能还大）</li>
</ul>
<h4><strong>SEO (搜索引擎优化)</strong></h4>
<ul>
	<li>使用 “搜索引擎喜欢的” URL，如：使用 <code>example.com/pages/45-article-title</code> 而不是 <code>example.com/index.php?page=45 </code>(陈皓注：这里的URL是说Wordpress的，后者是默认的)</li>
</ul>
<ul>
	<li>如果你的动态页面要使用 <code>#</code> ，那么请把其改成 <code>#!</code> ，而在服务端，你需要处理<code>$_REQUEST["_escaped_fragment_"]</code> 这是Google搜索引擎需要的。换句话说，<code>./#!page=1</code> 会被Google搜索引擎转成 <code>./?_escaped_fragments_=page=1。</code> （陈皓注：通常来说URL中的#后的东西都不会被传到服务器上，所以，为了要让Google可以抓取AJAX的东西，你需要使用#!，而Google会把“#!”转成“_escaped_fragment_”来向服务器发请求，Twitter的大量的链接者是#!的，比如：<a onclick="pageTracker._trackPageview('/outgoing/twitter.com/_/your_activity?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="https://twitter.com/#!/your_activity">https://twitter.com/#!/your_activity</a>）。另外，用户也许会使用Firefox 或 Chromium， <code>history.pushState({"foo":"bar"}, "About", "./?page=1");</code> 是一个很不错的命令。所以，就算是我们的地址栏上的地址改变了，页面也不会重新装载。这可以让你使用 <code>?</code> 而不是 <code>#!</code> 也能无刷地保住当前的动态的页面，这可以让AJAX的请求被浏览器记住。</li>
</ul>
<ul>
	<li>别使用 “click here” 这样的链接。这样一来，无法SEO，而且对于一些需要使用读屏人来说很不友好（陈皓注：关于读屏软件，可参看本站的“<a title="如果你看不见你还能编程吗？" href="http://coolshell.cn/articles/5514.html" target="_blank">如果看不见你还能编程吗</a>”）</li>
</ul>
<ul>
	<li>做一个 <a onclick="pageTracker._trackPageview('/outgoing/www.sitemaps.org/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.sitemaps.org/" rel="nofollow">XML sitemap</a>，并放在网端的根下 <code>/sitemap.xml</code>. （陈皓注：这个文件可以让搜索引擎了解你的网站图）</li>
	<li>当你有多个URL指向同一个网页的使用，使用 <a onclick="pageTracker._trackPageview('/outgoing/googlewebmastercentral.blogspot.com/2009/02/specify-your-canonical.html?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://googlewebmastercentral.blogspot.com/2009/02/specify-your-canonical.html" rel="nofollow"><code>&#60;link rel="canonical" ... /&#62;</code></a> 你可以使用 <a onclick="pageTracker._trackPageview('/outgoing/www.google.com/webmasters/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.google.com/webmasters/" rel="nofollow">Google Webmaster Tools</a> 来查看相关的问题。</li>
</ul>
<ul>
	<li>使用 <a onclick="pageTracker._trackPageview('/outgoing/www.google.com/webmasters/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.google.com/webmasters/" rel="nofollow">Google Webmaster Tools</a> 和 <a onclick="pageTracker._trackPageview('/outgoing/siteexplorer.search.yahoo.com/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://siteexplorer.search.yahoo.com/" rel="nofollow">Yahoo Site Explorer</a>.</li>
</ul>
<ul>
	<li>安装 <a onclick="pageTracker._trackPageview('/outgoing/www.google.com/analytics/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.google.com/analytics/" rel="nofollow">Google Analytics</a>  (或是别的开源的网站分析工具，如： <a onclick="pageTracker._trackPageview('/outgoing/piwik.org/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://piwik.org/" rel="nofollow">Piwik</a>).</li>
</ul>
<ul>
	<li>了解 <a onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Robots_exclusion_standard?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://en.wikipedia.org/wiki/Robots_exclusion_standard" rel="nofollow">robots.txt</a> 和搜索引擎爬虫是如何工作的。</li>
</ul>
<ul>
	<li>重定向请求 (使用 <code>301 重定向网站</code>) ，如果你要把 <code>www.example.com</code> 定向到 <code>example.com</code>(或是其它的变更) 这样可以防止Google的rank因为域名的变化发生改变。（陈皓注：301重定向一般用作域名变更）</li>
</ul>
<ul>
	<li>知道并不是所有的爬虫都是好的，有些爬虫的行为并不好。（陈皓注：比如向你的网站发大量的请求导致服务器性能低下）</li>
</ul>
<ul>
	<li>如果你有一些非文本的内容需要在 Google’s sitemap  中，比如视频什么的。<a onclick="pageTracker._trackPageview('/outgoing/stackoverflow.com/questions/72394/what-should-a-developer-know-before-building-a-public-web-site_167608?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://stackoverflow.com/questions/72394/what-should-a-developer-know-before-building-a-public-web-site#167608">Tim Farley的答案</a>，可以让你看到很多有价值的东西。</li>
</ul>
<h4><strong>技术</strong></h4>
<ul>
	<li>理解什么是 <a onclick="pageTracker._trackPageview('/outgoing/www.ietf.org/rfc/rfc2616.txt?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.ietf.org/rfc/rfc2616.txt" rel="nofollow">HTTP</a> 比如 GET, POST, sessions, cookies等，了解什么是 “stateless” 无状态。</li>
</ul>
<ul>
	<li>让你的 <a onclick="pageTracker._trackPageview('/outgoing/www.w3.org/TR/xhtml1/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.w3.org/TR/xhtml1/" rel="nofollow">XHTML</a>/<a onclick="pageTracker._trackPageview('/outgoing/www.w3.org/TR/REC-html40/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.w3.org/TR/REC-html40/" rel="nofollow">HTML</a> 和 <a onclick="pageTracker._trackPageview('/outgoing/www.w3.org/TR/CSS2/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.w3.org/TR/CSS2/" rel="nofollow">CSS</a> 符合 <a onclick="pageTracker._trackPageview('/outgoing/www.w3.org/TR/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.w3.org/TR/" rel="nofollow">W3C 规范</a>，并确认他们都是 <a onclick="pageTracker._trackPageview('/outgoing/validator.w3.org/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://validator.w3.org/" rel="nofollow">合格的</a>。我们的目标是避免浏览器的 “quirks mode”，并且可以让其更容易地能和非标准的浏览器工作，比如读屏器或移动设备。</li>
</ul>
<ul>
	<li>理解浏览器是怎么处理 JavaScript 的。（陈皓：你会看到有些Javascript代码在页面上前面，有些则是在后面，所以你需要对其了解清楚为什么是这样）</li>
</ul>
<ul>
	<li>了解浏览器是怎么装载 JavaScript，CSS和其它资源的，了解其对视觉上的影响。（陈皓注：10年前我做网页的时候因为HTML还很弱，所以只能使用table来布局，使用table布局的问题就是整个table读完后页面才会显示，用户的视觉体验并不好）。在某些情况下，你可能需要<a onclick="pageTracker._trackPageview('/outgoing/developer.yahoo.net/blog/archives/2007/07/high_performanc_5.html?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://developer.yahoo.net/blog/archives/2007/07/high_performanc_5.html" target="_blank">把你的脚本放在页面的后面</a>。</li>
</ul>
<ul>
	<li>理解 JavaScript 的 sandbox 是怎么怎么工作的，尤其是你想使用iframes。</li>
</ul>
<ul>
	<li>请注意 JavaScript 可能会被禁止，这样会让你的AJAX失效。就算是大多数用户都开启了Javascript功能，但是也可能在一些情况下脚本是不被运行的，比如移动终端上，搜索引擎抓网页的时候也并不会执行你的脚本。</li>
</ul>
<ul>
	<li>学习 <a onclick="pageTracker._trackPageview('/outgoing/www.bigoakinc.com/blog/when-to-use-a-301-vs-302-redirect/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.bigoakinc.com/blog/when-to-use-a-301-vs-302-redirect/" rel="nofollow">301 和 302 转向的区别</a> (这也是一个SEO的问题).</li>
</ul>
<ul>
	<li>尽可能多地学习你的部署平台。（比如：操作系统，Web Server：Apache/Nginx，防火墙，数据库，等等）</li>
</ul>
<ul>
	<li>考虑使用一个 <a onclick="pageTracker._trackPageview('/outgoing/stackoverflow.com/questions/167531/is-it-ok-to-use-a-css-reset-stylesheet?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://stackoverflow.com/questions/167531/is-it-ok-to-use-a-css-reset-stylesheet">Reset Style Sheet</a>.</li>
</ul>
<ul>
	<li>考虑使用 JavaScript 框架(如： <a onclick="pageTracker._trackPageview('/outgoing/jquery.com/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://jquery.com/" rel="nofollow">jQuery</a>, <a onclick="pageTracker._trackPageview('/outgoing/mootools.net/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://mootools.net/" rel="nofollow">MooTools</a>, <a onclick="pageTracker._trackPageview('/outgoing/www.prototypejs.org/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://www.prototypejs.org/" rel="nofollow">Prototype</a>, <a onclick="pageTracker._trackPageview('/outgoing/dojotoolkit.org/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://dojotoolkit.org/" rel="nofollow">Dojo</a> 或 <a onclick="pageTracker._trackPageview('/outgoing/developer.yahoo.com/yui/3/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://developer.yahoo.com/yui/3/" rel="nofollow">YUI 3</a>)，它们会很好的兼容于不同的浏览器。（陈皓注：强烈推荐你看一下本站的<a title="开源中最好的Web开发的资源" href="http://coolshell.cn/articles/4795.html" target="_blank">开源中最好的WEB开发资源</a>一文）</li>
</ul>
<ul>
	<li>把视觉效果和JS框架合在一起讨论，考虑使用一个Service，如：<a onclick="pageTracker._trackPageview('/outgoing/code.google.com/apis/libraries/devguide.html?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://code.google.com/apis/libraries/devguide.html" rel="nofollow">Google Libraries API</a> 来装载框架，这样可以让浏览器可能早就把这个JS框架已经cache了而不需要再从你的网站上下载了。</li>
</ul>
<h4><strong>Bug fixing</strong></h4>
<ul>
	<li>明白你会花20%的时间写代码，而80%的时候在维护，所以你要小心编码。（陈皓注：参看本站的“<a title="多些时间能少写些代码" href="http://coolshell.cn/articles/5686.html" target="_blank">多些时间可以少些代码</a>”一文）</li>
</ul>
<ul>
	<li>设计一个好的错误报告机制。</li>
</ul>
<ul>
	<li>设计一个入口可以让人们联系到你并给你建议和批评。</li>
</ul>
<ul>
	<li>为你开发的东西形成文档，这样可以让后来的人容易维护你的软件和系统。</li>
</ul>
<ul>
	<li>频繁备份（也可确保你的这些备份功能正常） <a onclick="pageTracker._trackPageview('/outgoing/stackoverflow.com/questions/72394/what-should-a-developer-know-before-building-a-public-web-site_73970?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://stackoverflow.com/questions/72394/what-should-a-developer-know-before-building-a-public-web-site#73970">Ed Lucas 的回答</a> 有一些忠告。你还需要有一个恢复策略，而不只是一个备份策略。</li>
</ul>
<ul>
	<li>使用一个版本控制系统来保存你的代码，如： <a onclick="pageTracker._trackPageview('/outgoing/subversion.apache.org/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://subversion.apache.org/" rel="nofollow">Subversion</a> 或 <a onclick="pageTracker._trackPageview('/outgoing/git-scm.org/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://git-scm.org/" rel="nofollow">Git</a>.</li>
</ul>
<ul>
	<li>别忘了做Acceptance Testing，使用 <a onclick="pageTracker._trackPageview('/outgoing/seleniumhq.org/?referer=http%3A%2F%2Fcoolshell.cn%2Farticles%2F6010.html');" href="http://seleniumhq.org/" rel="nofollow">Selenium</a> 能帮到你。</li>
</ul>
<ul>
	<li>确保你有足够的日志，你可以使用 log4j, log4n 或 log4r。如果出了问题，这是可以让你快速找到问题的方式。</li>
</ul>
<ul>
	<li>当你写日志的时候，确保你记录了你捕获了处理和未处理异常。报告和分析日志可以让你知道你网站的问题。</li>
</ul>
这里有多的东西被省略了，并不是因为那些可能不是有帮助的答案，而是因为那些东西都太细节了，超出了这个问题的范围，因为这本来就是一个Web开发需要了解东西的Overview。我想你可以去看一下其它人的答案，我有时间，我也会补充别人的答案进来。请随意编辑这个答案，因为可能有些东西忘了，也有可能有些东西不对。

（全文完）]]></description>
		<wfw:commentRss>http://www.xa01.cc/50.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>你会做Web上的用户登录功能吗？</title>
		<link>http://www.xa01.cc/46.html</link>
		<comments>http://www.xa01.cc/46.html#comments</comments>
		<pubDate>Wed, 18 Jan 2012 08:09:19 +0000</pubDate>
		<dc:creator>lv</dc:creator>
				<category><![CDATA[感悟]]></category>

		<guid isPermaLink="false">http://www.xa01.cc/?p=46</guid>
		<description><![CDATA[Web上的用户登录功能应该是最基本的功能了，可是在我看过一些站点的用户登录功能后，我觉得很有必要写一篇文章教大家怎么来做用户登录功能。下面的文章告诉大家这个功能可能并没有你所想像的那么简单，这是一个关系到用户安全的功能，希望大家能从下面的文章中能知道什么样的方法才是一个好的用户登录功能。<strong>以下内容，转载时请保持原文一致，并请注明作者和出处</strong>。
<h4>用户名和口令</h4>
首先，我们先来说说用户名和口令的事。这并不是本站第一次谈论这个事了。<a title="如何管理并设计你的口令" href="http://coolshell.cn/articles/2428.html" target="_blank">如何管理自己的口令</a>让你知道怎么管理自己的口令，<a title="破解你的口令" href="http://coolshell.cn/articles/3801.html" target="_blank">破解你的口令</a>让你知道在现代这样速度的计算速度下，用穷举法破解你的口令可能会是一件很轻松的事。在这里我想告诉从开发者的角度上来做设计这个用户名和口令的事。下面一几件规则：
<ul>
	<li><strong>限制用户输入一些非常容易被破解的口令</strong>。如什么qwert，123456, password之类，就像<a title="Twitter的禁用口令" href="http://coolshell.cn/articles/2451.html" target="_blank">twitter限制用户的口令</a>一样做一个口令的黑名单。另外，你可以限制用户口令的长度，是否有大小写，是否有数字，你可以用你的程序做一下校验。当然，这可能会让用户感到很不爽，所以，现在很多网站都提供了UX让用户知道他的口令强度是什么样的（比如<a title="另类UX让你输入强口令" href="http://coolshell.cn/articles/3877.html" target="_blank">这个有趣的UX</a>），这样可以让用户有一个选择，目的就是告诉用户——要想安全，先把口令设得好一点。</li>
</ul>
<ul>
	<li><strong>千万不要明文保存用户的口令</strong>。正如<a title="如何管理并设计你的口令" href="http://coolshell.cn/articles/2428.html" target="_blank">如何管理自己的口令</a>所说的一样，很多时候，用户都会用相同的ID相同的口令来登录很多网站。所以，如果你的网站明文保存的话，那么，如果你的数据被你的不良员工流传出去那对用户是灾难性的。所以，用户的口令一定要加密保存，最好是用不可逆的加密，如MD5或是SHA1之类的有hash算法的不可逆的加密算法。CSDN曾明文保存过用户的口令。（另，对于国内公司的品行以及有关部门的管理方式，我不敢保证国内网站以加密的方式保存你的口令。我觉得，做为一个有良知的人，我们应该加密保存用户的口令）</li>
</ul>
<div> </div>
<ul>
	<li><strong>是否让浏览器保存口令</strong>。我们有N多的方法可以不让浏览器保存用户名和口令。但是这可能对用户来说很不爽。因为在真实世界里谁也记得不住那么多的口令。很多用户可能会使用一些密码管理工具来保存密码，浏览器只是其中一种。是否让浏览器保存这个需要你做决定，重点是看一下你的系统的安全级别是否要求比较高，如果是的话，则不要让浏览器保存密码，并在网站明显的位置告诉用户——保存口令最安全的地方只有你的大脑。</li>
</ul>
<ul>
	<li><strong>口令在网上的传输</strong>。因为HTTP是明文协议，所以，用户名和口令在网上也是明文发送的，这个很不安全。你可以看看<a title="用Wireshark从http数据包中得到用户的登录信息" onclick="pageTracker._trackPageview('/outgoing/www.blogjava.net/heyang/archive/2011/04/05/340330.html?referer=http%3A%2F%2Fwww.baidu.com%2Fs%3Fwd%3D%25BA%25CE%25CE%25AAweb%25B9%25A6%25C4%25DC%26pn%3D10%26tn%3Dgctech_2_pg');" href="http://www.blogjava.net/heyang/archive/2011/04/05/340330.html" target="_blank">这篇文章</a>你就明白了。要做到加密传输就必需使用HTTPS协议。但是，在中国还是有很多网站的Web登录方式还在使用ActiveX控件，这可能成为IE6还大量存在的原因。我通常理解为这些ActiveX控件是为了反键盘记录程序的。 不过，我依然觉ActiveX控件不应该存在，因为在国外的众多安全很重要的站点上都看不到ActiveX的控件的身影。</li>
</ul>
<h4>用户登录状态</h4>
首先，我想告诉大家的是，因为HTTP是无状态的协议，也就是说，这个协议是无法记录用户访问状态的，其每次请求都是独立的无关联的，一笔是一笔。而我们的网站都是设计成多个页面的，所在页面跳转过程中我们需要知道用户的状态，尤其是用户登录的状态，这样我们在页面跳转后我们才知道是否可以让用户有权限来操作一些功能或是查看一些数据。

<strong>所以，我们每个页面都需要对用户的身份进行认证</strong>。当然，我们不可能让用户在每个页面上输入用户名和口令，这会让用户觉得我们的网站相当的SB。为了实现这一功能，用得最多的技术就是浏览器的cookie，我们会把用户登录的信息存放在客户端的cookie里，这样，我们每个页面都从这个cookie里获得用户是否登录的信息，从而达到记录状态，验证用户的目的。但是，你真的会用cookie吗？下面是使用cookie的一些原则。
<ul>
	<li><strong>千万不要在cookie中存放用户的密码</strong>。加密的密码都不行。因为这个密码可以被人获取并尝试离线穷举。所以，你一定不能把用户的密码保存在cookie中。我看到太多的站点这么干了。</li>
</ul>
<ul>
	<li><strong>正确设计“记住密码”</strong>。这个功能简直就是一个安全隐患，我觉得并不是所有的程序员都知道怎么设计这个事。一般的设计 是——一时用户勾选了这个功能，系统会生成一个cookie，cookie包括用户名和一个固定的散列值，这个固定的散列值一直使用。这样，你就可以在所有的设备和客户上都可以登录，而且可以有多个用户同时登录。这个并不是很安全。下面是一些更为安全的方法供你参考：
（——<em><strong>更新 2011/08/26，原文中有些小错误，并且说的不清楚，重新调整了一下——</strong></em>）</li>
</ul>
1）在cookie中，保存三个东西——<strong>用户名</strong>，<strong>登录序列</strong>，<strong>登录token</strong>。

<strong>用户名</strong>：明文存放。
<strong>登录序列</strong>：一个被MD5散列过的随机数，仅当强制用户输入口令时更新（如：用户修改了口令）。
<strong>登录token</strong>：一个被MD5散列过的随机数，仅一个登录session内有效，新的登录session会更新它。

2）上述三个东西会存在服务器上，服务器的验证用户需要验证客户端cookie里的这三个事。

3）这样的设计会有什么样的效果，会有下面的效果，

a）<strong>登录token</strong>是单实例登录。意思就是一个用户只能有一个登录实例。

b）<strong>登录序列</strong>是用来做盗用行为检测的。如果用户的cookie被盗后，盗用者使用这个cookie访问网站时，我们的系统是以为是合法用户，然后更新“<strong>登录token</strong>”，而真正的用户回来访问时，系统发现只有“<strong>用户名</strong>”和“<strong>登录序列</strong>”相同，但是“<strong>登录token</strong>” 不对，这样的话，系统就知道，这个用户可能出现了被盗用的情况，于是，系统可以清除并更改<strong>登录序列 </strong>和<strong> <strong>登录token</strong></strong>，这样就可以令所有的cookie失效，并要求用户输入口令。并给警告用户系统安全。

4）当然，<strong>上述这样的设计还是会有一些问题，比如：同一用户的不同设备登录，甚至在同一个设备上使用不同的浏览器保登录</strong>。一个设备会让另一个设备的<strong>登录token</strong>和<strong>登录序列</strong>失效，从而让其它设备和浏览器需要重新登录，并会造成cookie被盗用的假象。所以，你在服务器服还需要考虑- <strong>IP 地址</strong>，

a) 如果以口令方式登录，我们无需更新服务器的“<strong>登录序列</strong>”和 “<strong>登录token</strong>”（但需要更新cookie）。因为我们认为口令只有真正的用户知道。

b) 如果 <strong>IP相同</strong> ，那么，我们无需更新服务器的“<strong>登录序列</strong>”和 “<strong>登录token</strong>”（但需要更新cookie）。因为我们认为是同一用户有同一IP（当然，同一个局域网里也有同一IP，但我们认为这个局域网是用户可以控制的。网吧内并不推荐使用这一功能）。

c) 如果 （<strong>IP不同 </strong>&#38;&#38;<strong> 没有用口令登录</strong>），那么，“<strong>登录token</strong>” 就会在多个IP间发生变化（登录token在两个或多个ip间被来来回回的变换），当在一定时间内达到一定次数后，系统才会真正觉得被盗用的可能性很高，此时系统在后台清除“<strong>登录序列</strong>”和“<strong>登录token</strong>“，让Cookie失效，强制用户输入口令（或是要求用户更改口令），以保证多台设备上的cookie一致。
<ul>
	<li><strong>不要让cookie有权限访问所有的操作</strong>。否则就是XSS攻击，这个功能请参看<a title="新浪微博的XSS攻击" href="http://coolshell.cn/articles/4914.html" target="_blank">新浪微博的XSS攻击</a>。下面的这些功能一定要用户输入口令：</li>
</ul>
<div>1）修改口令。</div>
<div>2）修改电子邮件。（电子邮件通常用来找回用户密码，最好通发邮件或是发手机短信的方式修改，或者干脆就不让改一一用电子邮件做帐号名）</div>
<div>3）用户的隐私信息。</div>
<div>4）用户消费功能。</div>
<div>
<ul>
	<li><strong>权衡Cookie的过期时间。</strong>如果是永不过期，会有很不错的用户体验，但是这也会让用户很快就忘了登录密码。如果设置上过期期限，比如2周，一个月，那么可能会好一点，但是2周和一个月后，用户依然会忘了密码。尤其是用户在一些公共电脑上，如果保存了永久cookie的话，等于泄露了帐号。所以，对于cookie的过期时间我们还需要权衡。</li>
</ul>
</div>
<h4>找回口令的功能</h4>
找回口令的功能一定要提供。但是很多朋友并不知道怎么来设计这个功能。我们有很多找回口令的设计，下面我逐个点评一下。
<ul>
	<li><strong>千万不要使用安全问答</strong>。事实证明，这个环节很烦人，而且用户并不能很好的设置安全问答。什么，我的生日啊，我母亲的生日，等等。因为今天的互联网和以前不一样了，因为SNS，今天的互联比以前更真实了，我可以上facebook，开心，人人网，LinkedIn查到你的很多的真实的信息。通过这些信息我可以使用安全问答来重设你的口令。 这里需要说一下 Facebook，Facebook的安全问答很强大，还要你通过照片认人，呵呵。</li>
</ul>
<ul>
	<li><strong>不要重置用户的密码</strong>。因为这有可能让用户的密码遭到恶意攻击。当然，你要发个邮件给用户让其确认，用户点击邮件中的一个链接，你再重置。我并不推荐这样的方法，因为用户一般都会用笔记下来这个很难记的口令，然后登录系统，因为登录系统时使用了“记住密码”的功能，所以导致用户不会去修改密码，从而要么导到被写下来的密码被人盗取，要么又忘记了密码。</li>
</ul>
<ul>
	<li><strong>好一点的做法——通过邮件自行重置</strong>。当用户申请找回口令功能的时候，系统生成一个MD5唯一的随机字串（可通过UID+IP+timestamp+随机数），放在数据库中，然后设置上时限（比如1小时内），给用户发一个邮件，这个连接中包含那个MD5的字串的链接，用户通过点击那个链接来自己重新设置新的口令。</li>
</ul>
<ul>
	<li><strong>更好一点的做法——多重认证</strong>。比如：通过手机+邮件的方式让用户输入验证码。手机+邮件可能还不把握，因为手机要能会丢了，而我的手机可以访问我的邮箱。所以，使用U盾，SecureID（一个会变化的6位数token），或是通过人工的方式核实用户身份。当然，这主要看你的系统的安全级别了。</li>
</ul>
<h4>口令探测防守</h4>
<ul>
	<li><strong>使用验证码</strong>。验证码是后台随机产生的一个短暂的验证码，这个验证码一般是一个计算机很难识别的图片。这样就可以防止以程序的方式来尝试用户的口令。事实证明，这是最简单也最有效的方式。当然，总是让用户输入那些肉眼都看不清的验证码的用户体验不好，所以，可以折中一下。比如Google，当他发现一个IP地址发出大量的搜索后，其会要求你输入验证码。当他发现同一个IP注册了3个以上的gmail邮箱后，他需要给你发短信方式或是电话方式的验证码。</li>
</ul>
<ul>
	<li><strong>用户口令失败次数</strong>。调置口令失败的上限，如果失败过多，则把帐号锁了，需要用户以找回口令的方式来重新激活帐号。但是，这个功能可能会被恶意人使用。最好的方法是，增加其尝试的时间成本（以前的这篇文章说过一个<a title="如何防范密码被破解" href="http://coolshell.cn/articles/2078.html" target="_blank">增加时间成本的解密算法</a>）。如，两次口令尝试的间隔是5秒钟。三次以上错误，帐号被临时锁上30秒，5次以上帐号被锁1分钟，10次以上错误帐号被锁4小时……但是这会导致恶意用户用脚本来攻击，所以最好再加上验证码，验证码出错次数过多不禁止登录而是禁lP。</li>
</ul>
<ul>
	<li><strong>系统全局防守</strong>。上述的防守只针对某一个别用户。恶意者们深知这一点，所以，他们一般会动用“僵尸网络”轮着尝试一堆用户的口令，所以上述的那种方法可能还不够好。我们需要在系统全局域上监控所有的口令失败的次数。当然，这个需要我们平时没有受到攻击时的数据做为支持。比如你的系统，平均每天有5000次的口令错误的事件，那么你可以认为，当口令错误大幅超过这个数后，而且时间相对集中，就说明有黑客攻击。这个时候你怎么办？一般最常见使用的方法是让所有的用户输错口令后再次尝试的时间成本增加。</li>
</ul>
<div>最后，再说一下，关于用户登录，使用第三方的 OAuth 和 OpenID 也不失为一个很不错的选择。</div>
<h4>参考文章</h4>
<ul>
	<li><a onclick="pageTracker._trackPageview('/outgoing/www.owasp.org/index.php/Guide_to_Authentication?referer=http%3A%2F%2Fwww.baidu.com%2Fs%3Fwd%3D%25BA%25CE%25CE%25AAweb%25B9%25A6%25C4%25DC%26pn%3D10%26tn%3Dgctech_2_pg');" href="http://www.owasp.org/index.php/Guide_to_Authentication" rel="nofollow">OWASP Guide To Authentication</a></li>
	<li><a onclick="pageTracker._trackPageview('/outgoing/www.cs.umass.edu/_kevinfu/papers/webauth_tr.pdf?referer=http%3A%2F%2Fwww.baidu.com%2Fs%3Fwd%3D%25BA%25CE%25CE%25AAweb%25B9%25A6%25C4%25DC%26pn%3D10%26tn%3Dgctech_2_pg');" href="http://www.cs.umass.edu/~kevinfu/papers/webauth_tr.pdf" rel="nofollow">Dos and Don’ts of Client Authentication on the Web </a>（PDF）</li>
	<li><a onclick="pageTracker._trackPageview('/outgoing/fishbowl.pastiche.org/2004/01/19/persistent_login_cookie_best_practice/?referer=http%3A%2F%2Fwww.baidu.com%2Fs%3Fwd%3D%25BA%25CE%25CE%25AAweb%25B9%25A6%25C4%25DC%26pn%3D10%26tn%3Dgctech_2_pg');" href="http://fishbowl.pastiche.org/2004/01/19/persistent_login_cookie_best_practice/" rel="nofollow">Charles Miller’s Persistent Login Cookie Best Practice</a></li>
	<li><a onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/HTTP_cookie_Drawbacks_of_cookies?referer=http%3A%2F%2Fwww.baidu.com%2Fs%3Fwd%3D%25BA%25CE%25CE%25AAweb%25B9%25A6%25C4%25DC%26pn%3D10%26tn%3Dgctech_2_pg');" href="http://en.wikipedia.org/wiki/HTTP_cookie#Drawbacks_of_cookies" rel="nofollow">Wikipedia: HTTP cookie</a></li>
	<li><a onclick="pageTracker._trackPageview('/outgoing/cups.cs.cmu.edu/soups/2008/proceedings/p13Rabkin.pdf?referer=http%3A%2F%2Fwww.baidu.com%2Fs%3Fwd%3D%25BA%25CE%25CE%25AAweb%25B9%25A6%25C4%25DC%26pn%3D10%26tn%3Dgctech_2_pg');" href="http://cups.cs.cmu.edu/soups/2008/proceedings/p13Rabkin.pdf" rel="nofollow">Personal knowledge questions for fallback authentication: Security questions in the era of Facebook </a></li>
</ul>]]></description>
		<wfw:commentRss>http://www.xa01.cc/46.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>一根筋的第一篇文章</title>
		<link>http://www.xa01.cc/13.html</link>
		<comments>http://www.xa01.cc/13.html#comments</comments>
		<pubDate>Thu, 12 Jan 2012 09:17:50 +0000</pubDate>
		<dc:creator>一根筋</dc:creator>
				<category><![CDATA[所有分类]]></category>

		<guid isPermaLink="false">http://wp.hsw.cn/?p=13</guid>
		<description><![CDATA[文章是这样发吗？？？]]></description>
		<wfw:commentRss>http://www.xa01.cc/13.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

