﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-疯狂-随笔分类-java安全</title><link>http://www.blogjava.net/freeman1984/category/43930.html</link><description>         
        STANDING ON THE SHOULDERS OF GIANTS</description><language>zh-cn</language><lastBuildDate>Mon, 24 Dec 2012 20:16:05 GMT</lastBuildDate><pubDate>Mon, 24 Dec 2012 20:16:05 GMT</pubDate><ttl>60</ttl><item><title>关于tomcat和sessionCookieName和SESSION_PARAMETER_NAME以及disableURLRewriting参数原理和使用</title><link>http://www.blogjava.net/freeman1984/archive/2012/12/24/393402.html</link><dc:creator>疯狂</dc:creator><author>疯狂</author><pubDate>Mon, 24 Dec 2012 07:16:00 GMT</pubDate><guid>http://www.blogjava.net/freeman1984/archive/2012/12/24/393402.html</guid><wfw:comment>http://www.blogjava.net/freeman1984/comments/393402.html</wfw:comment><comments>http://www.blogjava.net/freeman1984/archive/2012/12/24/393402.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/freeman1984/comments/commentRss/393402.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/freeman1984/services/trackbacks/393402.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 关于tomcat和sessionCookieName和SESSION_PARAMETER_NAME以及disableURLRewriting参数原理和使用&nbsp;&nbsp;<a href='http://www.blogjava.net/freeman1984/archive/2012/12/24/393402.html'>阅读全文</a><img src ="http://www.blogjava.net/freeman1984/aggbug/393402.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/freeman1984/" target="_blank">疯狂</a> 2012-12-24 15:16 <a href="http://www.blogjava.net/freeman1984/archive/2012/12/24/393402.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数字证书原理(转)</title><link>http://www.blogjava.net/freeman1984/archive/2012/07/24/383817.html</link><dc:creator>疯狂</dc:creator><author>疯狂</author><pubDate>Tue, 24 Jul 2012 02:35:00 GMT</pubDate><guid>http://www.blogjava.net/freeman1984/archive/2012/07/24/383817.html</guid><wfw:comment>http://www.blogjava.net/freeman1984/comments/383817.html</wfw:comment><comments>http://www.blogjava.net/freeman1984/archive/2012/07/24/383817.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/freeman1984/comments/commentRss/383817.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/freeman1984/services/trackbacks/383817.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 数字证书原理 文中首先解释了加密解密的一些基础知识和概念，然后通过一个加密通信过程的例子说明了加密算法的作用，以及数字证书的出现所起的作用。接着对数字证书做一个详细的解释，并讨论一下windows中数字证书的管理，最后演示使用makecert生成数字证书。如果发现文中有错误的地方，或者有什么地方说得不够清楚，欢迎指出！1、基础知识&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;&nbsp;<a href='http://www.blogjava.net/freeman1984/archive/2012/07/24/383817.html'>阅读全文</a><img src ="http://www.blogjava.net/freeman1984/aggbug/383817.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/freeman1984/" target="_blank">疯狂</a> 2012-07-24 10:35 <a href="http://www.blogjava.net/freeman1984/archive/2012/07/24/383817.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OAuth简介</title><link>http://www.blogjava.net/freeman1984/archive/2011/07/29/355312.html</link><dc:creator>疯狂</dc:creator><author>疯狂</author><pubDate>Fri, 29 Jul 2011 03:19:00 GMT</pubDate><guid>http://www.blogjava.net/freeman1984/archive/2011/07/29/355312.html</guid><wfw:comment>http://www.blogjava.net/freeman1984/comments/355312.html</wfw:comment><comments>http://www.blogjava.net/freeman1984/archive/2011/07/29/355312.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/freeman1984/comments/commentRss/355312.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/freeman1984/services/trackbacks/355312.html</trackback:ping><description><![CDATA[<h1 id="firstHeading" class="firstHeading"><!-- /jumpto --><!-- bodytext -->
</h1>
<div class="floatright"></div>
<p><strong>OAuth</strong>（开放授权）是一个<font color="#ba0000">开放标准</font>，允许用户让第三方应用访问该用户在某一网站上存储的私密的资源（如照片，视频，联系人列表），而无需将用户名和密码提供给第三方应用。</p>
<p>OAuth允许用户提供一个令牌，而不是用户名和密码来访问他们存放在特定服务提供者的数据。每一个令牌授权一个特定的网站（例如，视频编辑网站)在特定的时段（例如，接下来的2小时内）内访问特定的资源（例如仅仅是某一相册中的视频）。这样，OAuth允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息，而不需要分享他们的访问许可或他们数据的所有内容。</p>
<p>OAuth是OpenID的一个补充，但是完全不同的服务。</p>
<h2><span id=".E8.AE.A4.E8.AF.81.E5.92.8C.E6.8E.88.E6.9D.83.E8.BF.87.E7.A8.8B" class="mw-headline">认证和授权过程</span></h2>
<p>在认证和授权的过程中涉及的三方包括：</p>
<div>
<ul><li><strong>服务提供方</strong>，用户使用服务提供方来存储受保护的资源，如照片，视频，联系人列表。</li><li><strong>用户</strong>，存放在服务提供方的受保护的资源的拥有者。</li><li><strong>客户端</strong>，要访问服务提供方资源的第三方应用，通常是网站，如提供照片打印服务的网站。在认证过程之前，客户端要向服务提供者申请客户端标识。</li></ul></div>
<p>使用OAuth进行认证和授权的过程如下所示:</p>
<ol><li><strong>用户</strong>访问<strong>客户端</strong>的网站，想操作用户存放在<strong>服务提供方</strong>的资源。</li><li><strong>客户端</strong>向<strong>服务提供方</strong>请求一个临时令牌。</li><li><strong>服务提供方</strong>验证<strong>客户端</strong>的身份后，授予一个临时令牌。</li><li><strong>客户端</strong>获得临时令牌后，将用户引导至<strong>服务提供方</strong>的授权页面请求用户授权。在这个过程中将临时令牌和客户端的回调连接发送给<strong>服务提供方</strong>。</li><li><strong>用户</strong>在<strong>服务提供方</strong>的网页上输入用户名和密码，然后授权该<strong>客户端</strong>访问所请求的资源。</li><li>授权成功后，<strong>服务提供方</strong>引导<strong>用户</strong>返回<strong>客户端</strong>的网页。</li><li><strong>客户端</strong>根据临时令牌从<strong>服务提供方</strong>那里获取访问令牌。</li><li><strong>服务提供方</strong>根据临时令牌和<strong>用户</strong>的授权情况授予<strong>客户端</strong>访问令牌。</li><li><strong>客户端</strong>使用获取的访问令牌访问存放在<strong>服务提供方</strong>上的受保护的资源。</li></ol>
<p>新浪oauth认证说明：<br /><a href="http://open.weibo.com/wiki/Oauth">http://open.weibo.com/wiki/Oauth</a><br />豆瓣oauth认证：<br /><a href="http://www.douban.com/service/apidoc/auth">http://www.douban.com/service/apidoc/auth</a></p><img src ="http://www.blogjava.net/freeman1984/aggbug/355312.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/freeman1984/" target="_blank">疯狂</a> 2011-07-29 11:19 <a href="http://www.blogjava.net/freeman1984/archive/2011/07/29/355312.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tomcat https</title><link>http://www.blogjava.net/freeman1984/archive/2011/06/25/353006.html</link><dc:creator>疯狂</dc:creator><author>疯狂</author><pubDate>Sat, 25 Jun 2011 15:06:00 GMT</pubDate><guid>http://www.blogjava.net/freeman1984/archive/2011/06/25/353006.html</guid><wfw:comment>http://www.blogjava.net/freeman1984/comments/353006.html</wfw:comment><comments>http://www.blogjava.net/freeman1984/archive/2011/06/25/353006.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/freeman1984/comments/commentRss/353006.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/freeman1984/services/trackbacks/353006.html</trackback:ping><description><![CDATA[<p>HTTPS（全称：Hypertext Transfer Protocol over Secure Socket Layer），是以安全为目标的HTTP通道，简单讲是HTTP的安全版。即HTTP下加入SSL层，HTTPS的安全基础是SSL，因此加密</p>
<p>的详细内容就需要SSL<br />　　SSL协议的握手过程<br />SSL 协议既用到了公钥加密技术又用到了对称加密技术，对称加密技术虽然比公钥加密技术的速度快，可是公钥加密技术提供了更好的身份认证技术。SSL 的握手协议非常有效的让客户和服</p>
<p>务器之间完成相互之间的身份认证，其主要过程如下： 　　<br />&#9312;客户端的浏览器向服务器传送客户端 SSL 协议的版本号，加密算法的种类，产生的随机数，以及其他服务器和客户端之间通讯所需要的各种信息。 　　<br />&#9313;服务器向客户端传送 SSL 协议的版本号，加密算法的种类，随机数以及其他相关信息，同时服务器还将向客户端传送自己的证书。 　　<br />&#9314;客户利用服务器传过来的信息验证服务器的合法性，服务器的合法性包括：证书是否过期，发行服务器证书的 CA 是否可靠，发行者证书的公钥能否正确解开服务器证书的&#8220;发行者的数字</p>
<p>签名&#8221;，服务器证书上的域名是否和服务器的实际域名相匹配。如果合法性验证没有通过，通讯将断开；如果合法性验证通过，将继续进行第四步。 　　<br />&#9315;用户端随机产生一个用于后面通讯的&#8220;对称密码&#8221;，然后用服务器的公钥（服务器的公钥从步骤&#9313;中的服务器的证书中获得）对其加密，然后将加密后的&#8220;预主密码&#8221;传给服务器。 　　<br />&#9316;如果服务器要求客户的身份认证（在握手过程中为可选），用户可以建立一个随机数然后对其进行数据签名，将这个含有签名的随机数和客户自己的证书以及加密过的&#8220;预主密码&#8221;一起传</p>
<p>给服务器。 　　<br />&#9317;如果服务器要求客户的身份认证，服务器必须检验客户证书和签名随机数的合法性，具体的合法性验证过程包括：客户的证书使用日期是否有效，为客户提供证书的CA 是否可靠，发行CA </p>
<p>的公钥能否正确解开客户证书的发行 CA 的数字签名，检查客户的证书是否在证书废止列表（CRL）中。检验如果没有通过，通讯立刻中断；如果验证通过，服务器将用自己的私钥解开加密的</p>
<p>&#8220;预主密码&#8221;，然后执行一系列步骤来产生主通讯密码（客户端也将通过同样的方法产生相同的主通讯密码）。 　　<br />&#9318;服务器和客户端用相同的主密码即&#8220;通话密码&#8221;，一个对称密钥用于 SSL 协议的安全数据通讯的加解密通讯。同时在 SSL 通讯过程中还要完成数据通讯的完整性，防止数据通讯中的任何</p>
<p>变化。 　　<br />&#9319;客户端向服务器端发出信息，指明后面的数据通讯将使用的步骤&#9318;中的主密码为对称密钥，同时通知服务器客户端的握手过程结束。 　　<br />&#9320;服务器向客户端发出信息，指明后面的数据通讯将使用的步骤&#9318;中的主密码为对称密钥，同时通知客户端服务器端的握手过程结束。 　　<br />&#9321;SSL 的握手部分结束，SSL 安全通道的数据通讯开始，客户和服务器开始使用相同的对称密钥进行数据通讯，同时进行通讯完整性的检验。</p>
<p>&nbsp;</p>
<p><br />下面是在tomcat下实现https，使用jdk自带的keytool工具生成自签名证书。</p>
<p>1 生成keystore文件，keystore文件用来存储密钥和证书<br />&nbsp;&nbsp; keystore的详细参数可使用 可使用keystore命令查看。<br />&nbsp;&nbsp; <br />keytool -genkeypair -keyalg rsa -keysize 2048 -sigalg sha1withrsa -validity 3600 -alias <a href="http://www.joe.com">www.joe.com</a> -keystore e:\ssl\joe.keystore<br />输入keystore密码：<br />再次输入新密码:<br />您的名字与姓氏是什么？<br />&nbsp; [Unknown]：&nbsp; <a href="http://www.joe.com">www.joe.com</a><br />您的组织单位名称是什么？<br />&nbsp; [Unknown]：&nbsp; joe<br />您的组织名称是什么？<br />&nbsp; [Unknown]：&nbsp; joe<br />您所在的城市或区域名称是什么？<br />&nbsp; [Unknown]：&nbsp; bj<br />您所在的州或省份名称是什么？<br />&nbsp; [Unknown]：&nbsp; bj<br />该单位的两字母国家代码是什么<br />&nbsp; [Unknown]：&nbsp; cn<br />CN=www.joe.com, OU=joe, O=joe, L=bj, ST=bj, C=cn 正确吗？<br />&nbsp; [否]：&nbsp; y</p>
<p>输入&lt;<a href="http://www.joe.com">www.joe.com</a>&gt;的主密码<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; （如果和 keystore 密码相同，按回车）：<br />2 导出自签名证书。正是平台需要导出csr文件并去权威的ca认证机构获取受信任证书，一般是收费的。<br />&nbsp;&nbsp; keytool -exportcert -alias <a href="http://www.joe.com">www.joe.com</a> -keystore e:\ssl\joe.keystore -file e:\ssl\joe.cer -rfc<br />输入keystore密码：<br />保存在文件中的认证 &lt;e:\ssl\joe.cer&gt;<br />下面配置tomcat(server.xml)使其支持https.<br />&lt;Connector port="443" protocol="HTTP/1.1" SSLEnabled="true"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxThreads="150" scheme="https" secure="true"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clientAuth="false" sslProtocol="TLS"&nbsp; keystoreFile="conf/joe.keystore" keystorePass="123456"/&gt;<br />&nbsp;&nbsp;&nbsp; </p>
<p>3 修改操作系统host文件，添加127.0.0.1 <a href="http://www.joe.com">www.joe.com</a></p>
<p>4 新建web应用httpstest<br />并添加indexjsp:<br />&nbsp;&lt;body&gt;<br />&nbsp;&nbsp;&nbsp; &lt;%<br />&nbsp;&nbsp;&nbsp;&nbsp; for(Enumeration en = request.getAttributeNames();en.hasMoreElements();){<br />&nbsp;&nbsp;&nbsp; &nbsp;String name = (String)en.nextElement();<br />&nbsp;&nbsp;&nbsp; &nbsp;out.println(name);<br />&nbsp;&nbsp;&nbsp; &nbsp;out.println("="+request.getAttribute(name));<br />&nbsp;&nbsp;&nbsp; &nbsp;out.println();<br />&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; %&gt;<br />&nbsp; &lt;/body&gt;</p>
<p>5 为了让浏览器信任我们的证书，需要在浏览器导入我们的证书为信任根证书。<br />6 访问：<a href="https://www.joe.com/httpstest">https://www.joe.com/httpstest</a><br />输出：<br />javax.servlet.request.ssl_session =4e05eb849ac41a45b56725488b68c28cc8c2ea94e2ec599852e1665297b2822b <br />javax.servlet.request.key_size =128 <br />javax.servlet.request.cipher_suite =SSL_RSA_WITH_RC4_128_MD5 (通讯的加密信息，由浏览器和服务器协商确定)。</p>
<p>&nbsp;</p><img src ="http://www.blogjava.net/freeman1984/aggbug/353006.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/freeman1984/" target="_blank">疯狂</a> 2011-06-25 23:06 <a href="http://www.blogjava.net/freeman1984/archive/2011/06/25/353006.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WEB应用中的身份验证(1)--基本身份验证BASIC authorization method </title><link>http://www.blogjava.net/freeman1984/archive/2011/03/22/346772.html</link><dc:creator>疯狂</dc:creator><author>疯狂</author><pubDate>Tue, 22 Mar 2011 10:33:00 GMT</pubDate><guid>http://www.blogjava.net/freeman1984/archive/2011/03/22/346772.html</guid><wfw:comment>http://www.blogjava.net/freeman1984/comments/346772.html</wfw:comment><comments>http://www.blogjava.net/freeman1984/archive/2011/03/22/346772.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/freeman1984/comments/commentRss/346772.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/freeman1984/services/trackbacks/346772.html</trackback:ping><description><![CDATA[<p>在任何一种WEB应用开发中，不论大中小规模的，每个开发者都会遇到一些需要保护程序数据的问题，涉及到用户的LOGIN ID和PASSWORD。那么如何执行验证方式更好呢？实际上，有很多方式来实现。在本文里，我们不会把所有的验证方法都考虑到，我们的目的是让你学会如何以最简单最方便的验证方法来完成。下面将讨论基本验证方式之一（BASIC authorization method）</p>
<p>要搭建整个流程需要四个阶段：</p>
<p>一、建立测试用数据库<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们这里用Mysql进行测试，其他数据库完全一样。<br />
&nbsp;&nbsp;&nbsp;&nbsp;1、创建用户表<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;CREATE TABLE users (<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;id int(11) NOT NULL auto_increment,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;username varchar(20) NOT NULL,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;password varchar(20) NOT NULL,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;PRIMARY KEY&nbsp; (id)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;) </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;2、创建权限表（此事例中用不到）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;CREATE TABLE roles(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;id int(11) NOT NULL auto_increment,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;rolename varchar(20) NOT NULL,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;PRIMARY KEY&nbsp; (id)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;3、创建用户－权限对应表<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CREATE TABLE user_roles (<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; id int(11) NOT NULL auto_increment,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; username varchar(20) NOT NULL,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rolename varchar(20) NOT NULL,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PRIMARY KEY&nbsp; (id)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;4、插入数据<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insert into users(username,password) values('zhangdongyu', 'loveyuanyuan')<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insert into roles(rolename) values('manager')<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insert into user_roles(username,rolename) values('zhangdongyu', 'manager')<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
二、修改${tomcat}\conf\server.xml<br />
&nbsp;&nbsp;找到<br />
&nbsp;&nbsp;&nbsp;&lt;!--<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Realm className="org.apache.catalina.realm.MemoryRealm" /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 在上面这句话下面添加一下内容：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;Realm <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;className="org.apache.catalina.realm.JDBCRealm" <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;debug="99"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;driverName="org.gjt.mm.mysql.Driver" <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;connectionURL="jdbc:mysql://localhost/weblogin" &lt;!--数据库连接地址--&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;connectionName="root"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--数据库用户名--&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;connectionPassword="123"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--数据库密码--&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;userTable="users" &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--用户表--&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;userNameCol="username" &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--用户名列--&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;userCredCol="password"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--密码列--&gt;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;userRoleTable="user_roles" &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--用户权限对应表--&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;roleNameCol="rolename" &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--权限列--&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;/&gt;&nbsp;&nbsp;&nbsp;</p>
<p>三、创建工程<br />
&nbsp;&nbsp;在Eclipse创建一个web工程sercurityTest，在WebRoot下面创建一个文件夹admin(也可在里面建立几个文件)</p>
<p><br />
&nbsp;&nbsp;<img style="width: 222px; height: 137px" alt="Eclipse截图" src="http://p.blog.csdn.net/images/p_blog_csdn_net/swengineer/1.jpg" width="146" height="110" /></p>
<p><br />
&nbsp;&nbsp;在web.xml文件中添加以下片段：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;security-constraint&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;web-resource-collection&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;web-resource-name&gt;Web Demo&lt;/web-resource-name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;url-pattern&gt;/admin/*&lt;/url-pattern&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/web-resource-collection&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;auth-constraint&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;role-name&gt;<font style="background-color: #33cccc">manager</font>&lt;/role-name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/auth-constraint&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/security-constraint&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;login-config&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;auth-method&gt;BASIC&lt;/auth-method&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;realm-name&gt;Web Demo&lt;/realm-name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/login-config&gt;</p>
<p>四、重启Tomcat，使设置生效</p>
<p>总结测试：<br />
&nbsp;&nbsp;通过上面的四部分配置，当你再次访问程序中受保护的地址，如:http://localhost/sercurityTest/admin时<br />
&nbsp;&nbsp;会弹出验证对话框，让你输入用户名和密码，只有输入库中的用户名密码并且该用户有manager权限时才能进<br />
&nbsp;&nbsp;入受保护目录。<img style="width: 322px; height: 235px" alt="弹出验证" src="http://p.blog.csdn.net/images/p_blog_csdn_net/swengineer/2.jpg" width="272" height="201" /><br />
</p>
<br />
转载自：http://blog.csdn.net/swengineer/archive/2006/12/01/1424020.aspx
<img src ="http://www.blogjava.net/freeman1984/aggbug/346772.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/freeman1984/" target="_blank">疯狂</a> 2011-03-22 18:33 <a href="http://www.blogjava.net/freeman1984/archive/2011/03/22/346772.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Cookie和Session</title><link>http://www.blogjava.net/freeman1984/archive/2010/09/09/331501.html</link><dc:creator>疯狂</dc:creator><author>疯狂</author><pubDate>Thu, 09 Sep 2010 05:26:00 GMT</pubDate><guid>http://www.blogjava.net/freeman1984/archive/2010/09/09/331501.html</guid><wfw:comment>http://www.blogjava.net/freeman1984/comments/331501.html</wfw:comment><comments>http://www.blogjava.net/freeman1984/archive/2010/09/09/331501.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/freeman1984/comments/commentRss/331501.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/freeman1984/services/trackbacks/331501.html</trackback:ping><description><![CDATA[<p><br />
一、cookie机制和session机制的区别<br />
***********************************************************************<br />
具体来说cookie机制采用的是在客户端保持状态的方案，而session机制采用的是在服务器端保持状态的方案。<br />
同时我们也看到，由于才服务器端保持状态的方案在客户端也需要保存一个标识，所以session<br />
机制可能需要借助于cookie机制来达到保存标识的目的，但实际上还有其他选择<br />
***********************************************************************</p>
<p>二、会话cookie和持久cookie的区别<br />
***********************************************************************<br />
如果不设置过期时间，则表示这个cookie生命周期为浏览器会话期间，只要关闭浏览器窗口，cookie就消失了。这种生命期为浏览会话期的cookie被称为会话cookie。会话cookie一般不保存在硬盘上而是保存在内存里。<br />
　　如果设置了过期时间，浏览器就会把cookie保存到硬盘上，关闭后再次打开浏览器，这些cookie依然有效直到超过设定的过期时间。<br />
　　存储在硬盘上的cookie可以在不同的浏览器进程间共享，比如两个IE窗口。而对于保存在内存的cookie，不同的浏览器有不同的处理方式。<br />
***********************************************************************</p>
<p>三、如何利用实现自动登录<br />
***********************************************************************<br />
　　当用户在某个网站注册后，就会收到一个惟一用户ID的cookie。客户后来重新连接时，这个<br />
用户ID会自动返回，服务器对它进行检查，确定它是否为注册用户且选择了自动登录，从而使用户务需给出明确的用户名和密码，就可以访问服务器上的资源。<br />
************************************************************************</p>
<p>四、如何根据用户的爱好定制站点<br />
************************************************************************<br />
　　网站可以使用cookie记录用户的意愿。对于简单的设置，网站可以直接将页面的设置存储在cookie中完成定制。然而对于更复杂的定制，网站只需仅将一个惟一的标识符发送给用户，由服务器端的数据库存储每个标识符对应的页面设置。<br />
************************************************************************</p>
<p>五、cookie的发送<br />
************************************************************************<br />
1.创建Cookie对象<br />
2.设置最大时效<br />
3.将Cookie放入到HTTP响应报头<br />
如果你创建了一个cookie，并将他发送到浏览器，默认情况下它是一个会话级别的cookie:存储在浏览器的内存中，用户退出浏览器之后被删除。如果你希望浏览器将该cookie存储在磁盘上，则<br />
需要使用maxAge，并给出一个以秒为单位的时间。将最大时效设为0则是命令浏览器删除该cookie。<br />
发送cookie需要使用HttpServletResponse的addCookie方法，将cookie插入到一个Set-Cookie　HTTP请求报头中。由于这个方法并不修改任何之前指定的Set-Cookie报头，而是创建新的报头，因此我们将这个方法称为是addCookie，而非setCookie。同样要记住响应报头必须在任何文档内容发送到客户端之前设置。</p>
<p>六、cookie的读取<br />
*************************************************************************<br />
1.调用request.getCookie<br />
要获取有浏览器发送来的cookie，需要调用HttpServletRequest的getCookies方法，这个调用返回Cookie对象的数组，对应由HTTP请求中Cookie报头输入的值。<br />
2.对数组进行循环，调用每个cookie的getName方法，直到找到感兴趣的cookie为止<br />
　cookie与你的主机(域)相关，而非你的servlet或JSP页面。因而，尽管你的servlet可能只发送了单个cookie，你也可能会得到许多不相关的cookie。<br />
例如：<br />
　　String cookieName = &#8220;userID&#8221;;<br />
&nbsp;&nbsp;&nbsp; Cookie cookies[] = request.getCookies();<br />
&nbsp;&nbsp;&nbsp; if (cookies!=null){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i=0;i&lt;cookies.length;i++){<br />
&nbsp;&nbsp;&nbsp; Cookie cookie = cookies[i];<br />
&nbsp;&nbsp;&nbsp; if (cookieName.equals(cookie.getName())){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doSomethingWith(cookie.getValue());<br />
}<br />
}<br />
}<br />
************************************************************************</p>
<p>七、如何使用cookie检测初访者<br />
************************************************************************<br />
A.调用HttpServletRequest.getCookies()获取Cookie数组<br />
B.在循环中检索指定名字的cookie是否存在以及对应的值是否正确<br />
C.如果是则退出循环并设置区别标识<br />
D.根据区别标识判断用户是否为初访者从而进行不同的操作<br />
************************************************************************</p>
<p>八、使用cookie检测初访者的常见错误<br />
************************************************************************<br />
不能仅仅因为cookie数组中不存在在特定的数据项就认为用户是个初访者。如果cookie数组为null，客户可能是一个初访者，也可能是由于用户将cookie删除或禁用造成的结果。<br />
但是，如果数组非null,也不过是显示客户曾经到过你的网站或域，并不能说明他们曾经访问过你的servlet。其它servlet、JSP页面以及非Java Web应用都可以设置cookie，依据路径的设置，其中的任何cookie都有可能返回给用户的浏览器。<br />
正确的做法是判断cookie数组是否为空且是否存在指定的Cookie对象且值正确。<br />
************************************************************************</p>
<p>九、使用cookie属性的注意问题<br />
************************************************************************<br />
　　属性是从服务器发送到浏览器的报头的一部分；但它们不属于由浏览器返回给服务器的报头。　<br />
　　因此除了名称和值之外，cookie属性只适用于从服务器输出到客户端的cookie；服务器端来自于浏览器的cookie并没有设置这些属性。　<br />
　　因而不要期望通过request.getCookies得到的cookie中可以使用这个属性。这意味着，你不能仅仅通过设置cookie的最大时效，发出它，在随后的输入数组中查找适当的cookie,读取它的值，修改它并将它存回Cookie，从而实现不断改变的cookie值。<br />
************************************************************************</p>
<p>十、如何使用cookie记录各个用户的访问计数<br />
************************************************************************<br />
1.获取cookie数组中专门用于统计用户访问次数的cookie的值<br />
2.将值转换成int型<br />
3.将值加1并用原来的名称重新创建一个Cookie对象<br />
4.重新设置最大时效<br />
5.将新的cookie输出<br />
************************************************************************</p>
<p>十一、session在不同环境下的不同含义<br />
************************************************************************<br />
session，中文经常翻译为会话，其本来的含义是指有始有终的一系列动作/消息，比如打电话是从拿起电话拨号到挂断电话这中间的一系列过程可以称之为一个session。<br />
然而当session一词与网络协议相关联时，它又往往隐含了&#8220;面向连接&#8221;和/或&#8220;保持状态&#8221;这样两个含义。<br />
　　session在Web开发环境下的语义又有了新的扩展，它的含义是指一类用来在客户端与服务器端之间保持状态的解决方案。有时候Session也用来指这种解决方案的存储结构。<br />
************************************************************************</p>
<p>十二、session的机制<br />
************************************************************************<br />
　　session机制是一种服务器端的机制，服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。<br />
但程序需要为某个客户端的请求创建一个session的时候，服务器首先检查这个客户端的请求里是否包含了一个session标识－称为session id,如果已经包含一个session id则说明以前已经为此客户创建过session，服务器就按照session id把这个session检索出来使用(如果检索不到，可能会新建一个，这种情况可能出现在服务端已经删除了该用户对应的session对象，但用户人为地在请求的URL后面附加上一个JSESSION的参数)。<br />
如果客户请求不包含session id，则为此客户创建一个session并且生成一个与此session相关联的session id，这个session id将在本次响应中返回给客户端保存。<br />
************************************************************************</p>
<p>十三、保存session id的几种方式<br />
************************************************************************<br />
A．保存session id的方式可以采用cookie，这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器。<br />
B．由于cookie可以被人为的禁止，必须有其它的机制以便在cookie被禁止时仍然能够把session id传递回服务器，经常采用的一种技术叫做URL重写，就是把session id附加在URL路径的后面，附加的方式也有两种，一种是作为URL路径的附加信息，另一种是作为查询字符串附加在URL后面。网络在整个交互过程中始终保持状态，就必须在每个客户端可能请求的路径后面都包含这个session id。<br />
C．另一种技术叫做表单隐藏字段。就是服务器会自动修改表单，添加一个隐藏字段，以便在表单提交时能够把session id传递回服务器。<br />
************************************************************************</p>
<p>十四、session什么时候被创建<br />
************************************************************************<br />
一个常见的错误是以为session在有客户端访问时就被创建，然而事实是直到某server端程序(如Servlet)调用HttpServletRequest.getSession(true)这样的语句时才会被创建。<br />
************************************************************************</p>
<p>十五、session何时被删除<br />
************************************************************************<br />
session在下列情况下被删除：<br />
A．程序调用HttpSession.invalidate()<br />
B．距离上一次收到客户端发送的session id时间间隔超过了session的最大有效时间<br />
C．服务器进程被停止</p>
<p>再次注意关闭浏览器只会使存储在客户端浏览器内存中的session cookie失效，不会使服务器端的session对象失效。<br />
************************************************************************</p>
<p>十六、URL重写有什么缺点<br />
************************************************************************<br />
　　　对所有的URL使用URL重写，包括超链接，form的action，和重定向的URL。每个引用你的站点的URL，以及那些返回给用户的URL(即使通过间接手段，比如服务器重定向中的Location字段)都要添加额外的信息。<br />
　　　这意味着在你的站点上不能有任何静态的HTML页面(至少静态页面中不能有任何链接到站点动态页面的链接)。因此，每个页面都必须使用servlet或JSP动态生成。即使所有的页面都动态生成，如果用户离开了会话并通过书签或链接再次回来，会话的信息都会丢失，因为存储下来的链接含有错误的标识信息－该URL后面的SESSION ID已经过期了。　　<br />
************************************************************************</p>
<p>十七、使用隐藏的表单域有什么缺点<br />
************************************************************************<br />
&nbsp;&nbsp;&nbsp; 仅当每个页面都是有表单提交而动态生成时，才能使用这种方法。单击常规的&lt;A HREF..&gt;超文本链接并不产生表单提交，因此隐藏的表单域不能支持通常的会话跟踪，只能用于一系列特定的操作中，比如在线商店的结账过程<br />
************************************************************************</p>
<p>十八、会话跟踪的基本步骤<br />
************************************************************************<br />
1．访问与当前请求相关的会话对象<br />
2．查找与会话相关的信息<br />
3．存储会话信息<br />
4．废弃会话数据<br />
************************************************************************</p>
<p>十九、getSession()/getSession(true)、getSession(false)的区别<br />
************************************************************************<br />
getSession()/getSession(true)：当session存在时返回该session，否则新建一个session并返回该对象<br />
getSession(false)：当session存在时返回该session，否则不会新建session，返回null<br />
************************************************************************</p>
<p>二十、如何将信息于会话关联起来<br />
************************************************************************<br />
　　setAttribute会替换任何之前设定的值；如果想要在不提供任何代替的情况下移除某个值，则应使用removeAttribute。这个方法会触发所有实现了HttpSessionBindingListener接口的值的valueUnbound<br />
方法。<br />
************************************************************************</p>
<p>二十一、会话属性的类型有什么限制吗<br />
************************************************************************<br />
通常会话属性的类型只要是Object就可以了。除了null或基本类型，如int,double,boolean。<br />
如果要使用基本类型的值作为属性，必须将其转换为相应的封装类对象<br />
************************************************************************</p>
<p>二十二、如何废弃会话数据<br />
************************************************************************<br />
A．只移除自己编写的servlet创建的数据：<br />
&nbsp;&nbsp; 调用removeAttribute(&#8220;key&#8221;)将指定键关联的值废弃<br />
B．删除整个会话(在当前Web应用中)：<br />
&nbsp;&nbsp; 调用invalidate，将整个会话废弃掉。这样做会丢失该用户的所有会话数据，而非仅仅由我们<br />
servlet或JSP页面创建的会话数据<br />
C．将用户从系统中注销并删除所有属于他(或她)的会话<br />
&nbsp;&nbsp; 调用logOut，将客户从Web服务器中注销，同时废弃所有与该用户相关联的会话(每个Web应用至多一个)。这个操作有可能影响到服务器上多个不同的Web应用<br />
************************************************************************</p>
<p>二十三、使用isNew来判断用户是否为新旧用户的错误做法<br />
************************************************************************<br />
public boolean isNew()方法如果会话尚未和客户程序(浏览器)发生任何联系，则这个方法返回true，这一般是因为会话是新建的，不是由输入的客户请求所引起的。<br />
但如果isNew返回false，只不过是说明他之前曾经访问该Web应用，并不代表他们曾访问过我们的servlet或JSP页面。<br />
因为session是与用户相关的，在用户之前访问的每一个页面都有可能创建了会话。因此isNew为false只能说用户之前访问过该Web应用，session可以是当前页面创建，也可能是由用户之前访问过的页面创建的。<br />
正确的做法是判断某个session中是否存在某个特定的key且其value是否正确<br />
************************************************************************</p>
<p>二十四、Cookie的过期和Session的超时有什么区别<br />
************************************************************************<br />
会话的超时由服务器来维护，它不同于Cookie的失效日期。首先，会话一般基于驻留内存的cookie<br />
不是持续性的cookie，因而也就没有截至日期。即使截取到JSESSIONID cookie，并为它设定一个失效日期发送出去。浏览器会话和服务器会话也会截然不同。<br />
************************************************************************</p>
<p>二十五、session cookie和session对象的生命周期是一样的吗<br />
************************************************************************<br />
当用户关闭了浏览器虽然session cookie已经消失，但session对象仍然保存在服务器端<br />
************************************************************************</p>
<p>二十六、是否只要关闭浏览器，session就消失了<br />
************************************************************************<br />
程序一般都是在用户做log off的时候发个指令去删除session，然而浏览器从来不会主动在关闭之前通知服务器它将要被关闭，因此服务器根本不会有机会知道浏览器已经关闭。服务器会一直保留这个会话对象直到它处于非活动状态超过设定的间隔为止。<br />
之所以会有这种错误的认识，是因为大部分session机制都使用会话cookie来保存session id，而关闭浏览器后这个session id就消失了，再次连接到服务器时也就无法找到原来的session。<br />
如果服务器设置的cookie被保存到硬盘上，或者使用某种手段改写浏览器发出的HTTP请求报头，把原来的session id发送到服务器，则再次打开浏览器仍然能够找到原来的session。<br />
恰恰是由于关闭浏览器不会导致session被删除，迫使服务器为session设置了一个失效时间，当距离客户上一次使用session的时间超过了这个失效时间时，服务器就可以认为客户端已经停止了活动，才会把session删除以节省存储空间。<br />
　　由此我们可以得出如下结论：<br />
　　关闭浏览器，只会是浏览器端内存里的session cookie消失，但不会使保存在服务器端的session对象消失，同样也不会使已经保存到硬盘上的持久化cookie消失。<br />
************************************************************************</p>
<p><br />
二十七、打开两个浏览器窗口访问应用程序会使用同一个session还是不同的session<br />
************************************************************************<br />
通常session cookie是不能跨窗口使用的，当你新开了一个浏览器窗口进入相同页面时，系统会赋予你一个新的session id，这样我们信息共享的目的就达不到了。<br />
此时我们可以先把session id保存在persistent cookie中(通过设置session的最大有效时间)，然后在新窗口中读出来，就可以得到上一个窗口的session id了，这样通过session cookie和persistent cookie的结合我们就可以实现了跨窗口的会话跟踪。<br />
************************************************************************</p>
<p>二十八、如何使用会话显示每个客户的访问次数<br />
************************************************************************<br />
由于客户的访问次数是一个整型的变量，但session的属性类型中不能使用int，double，boolean等基本类型的变量，所以我们要用到这些基本类型的封装类型对象作为session对象中属性的值<br />
　　但像Integer是一种不可修改(Immutable)的数据结构：构建后就不能更改。这意味着每个请求都必须创建新的Integer对象，之后使用setAttribute来代替之前存在的老的属性的值。例如：<br />
HttpSession session = request.getSession();<br />
SomeImmutalbeClass value = (SomeImmutableClass)session.getAttribute(&#8220;SomeIdentifier&#8221;);<br />
if (value= =null){<br />
&nbsp;&nbsp;&nbsp; value = new SomeImmutableClass(&#8230;);　// 新创建一个不可更改对象<br />
}else{<br />
&nbsp;&nbsp;&nbsp; value = new SomeImmutableClass(calculatedFrom(value)); // 对value重新计算后创建新的对象<br />
}<br />
session.setAttribute(&#8220;someIdentifier&#8221;,value); // 使用新创建的对象覆盖原来的老的对象<br />
************************************************************************</p>
<p>二十九、如何使用会话累计用户的数据<br />
************************************************************************<br />
使用可变的数据结构，比如数组、List、Map或含有可写字段的应用程序专有的数据结构。通过这种方式，除非首次分配对象，否则不需要调用setAttribute。例如</p>
<p>HttpSession session = request.getSession();<br />
SomeMutableClass value = (SomeMutableClass)session.getAttribute(&#8220;someIdentifier&#8221;);<br />
if(value = = null){<br />
&nbsp;&nbsp;&nbsp; value = new SomeMutableClass(&#8230;);<br />
&nbsp;&nbsp;&nbsp; session.setAttribute(&#8220;someIdentifier&#8221;,value);<br />
}else{<br />
&nbsp;&nbsp;&nbsp; value.updateInternalAttribute(&#8230;);&nbsp;&nbsp;&nbsp;&nbsp; // 如果已经存在该对象则更新其属性而不需重新设置属性<br />
}<br />
************************************************************************</p>
<p>三十、不可更改对象和可更改对象在会话数据更新时的不同处理<br />
************************************************************************<br />
不可更改对象因为一旦创建之后就不能更改，所以每次要修改会话中属性的值的时候，都需要<br />
调用setAttribute(&#8220;someIdentifier&#8221;,newValue)来代替原有的属性的值，否则属性的值不会被更新<br />
可更改对象因为其自身一般提供了修改自身属性的方法，所以每次要修改会话中属性的值的时<br />
候，只要调用该可更改对象的相关修改自身属性的方法就可以了。这意味着我们就不需要调<br />
用setAttribute方法了</p>
<p>************************************************************************<br />
2.cookies的属性有：Domain(域)：哪个站点发的哪个站点拿走<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Expires:是否过期<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Haskeys:是否包含关键<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; path:存放的路径<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; secure:是否安全<br />
注：－－－cookies的设置在 sever端设置，路径与域一起构成cookie的作用范围?<br />
这个是什么意思的啊？为什么会是在服务器端进行设置的呢？<br />
&nbsp;&nbsp;&nbsp; 若不设置过期时间，则表示这个cookie的生命期为浏览器会话期间，关闭浏览器窗口，cookie就消失。这种生命期为浏览器会话期的cookie被称为会话cookie。会话cookie一般不存储在硬盘上而是保存在内存里，当然这种行为并不是规范规定的。若设置了过期时间，浏览器就会把cookie 保存到硬盘上，关闭后再次打开浏览器，这些cookie仍然有效直到超过设定的过期时间。存储在硬盘上的cookie可以在不同的浏览器进程间共享，比如两个IE窗口。而对于保存在内存里的cookie，不同的浏览器有不同的处理方式<br />
IE与FF的区别哦！FF是共享的而IE当打开不同的窗口的时候是不共享 的<br />
3.session(会话)：适用于同一客户在一个站点，不同页面上的浏览；适用于同一客户在一个页面上，不断的刷新。<br />
6.当程序需要为某个客户端的请求创建一个session时，服务器首先检查这个客户端的请求里是否已包含了一个session标识（称为session id），如果已包含则说明以前已经为此客户端创建过session，服务器就按照session id把这个session检索出来使用（检索不到，会新建一个），如果客户端请求不包含session id，则为此客户端创建一个session并且生成一个与此session相关联的session id，session id的值应该是一个既不会重复，又不容易被找到规律以仿造的字符串，这个session id将被在本次响应中返回给客户端保存。</p>
<p>IE中: <br />
有效的窗中包括 <br />
1.Session对象只在建立Session对象的窗口中有效。 <br />
2.在建立Session对象的窗口中新开链接的窗口 <br />
无效的窗口包括 <br />
1.直接启动IE浏览器的窗口 <br />
2.不是在建立Session对象的窗口中新开链接的窗口 </p>
<p>***********************************************************************<br />
cookie的内容主要包括：名字，值，过期时间，路径和域。<br />
其中,</p>
<p>&nbsp;&nbsp;&nbsp; 域可以指定某一个域比如.google.com，相当于总店招牌，比如宝洁公司，也可以指定一个域下的具体某台机器比如www.google.com或者froogle.google.com，可以用飘柔来做比。<br />
路径就是跟在域名后面的URL路径，比如/或者/foo等等，可以用某飘柔专柜做比。<br />
&nbsp;&nbsp; 路径与域合在一起就构成了cookie的作用范围。<br />
如果不设置过期时间，则表示这个cookie的生命期为浏览器会话期间，只要关闭浏览器窗口，cookie就消失了。这种生命期为浏览器会话期的 cookie被称为会话cookie。会话cookie一般不存储在硬盘上而是保存在内存里，当然这种行为并不是规范规定的。如果设置了过期时间，浏览器就会把cookie保存到硬盘上，关闭后再次打开浏览器，这些cookie仍然有效直到超过设定的过期时间。</p>
<p>&nbsp;&nbsp; 存储在硬盘上的cookie可以在不同的浏览器进程间共享，比如两个IE窗口。而对于保存在内存里的cookie，不同的浏览器有不同的处理方式。对于IE，在一个打开的窗口上按Ctrl-N（或者从文件菜单）打开的窗口可以与原窗口共享，而使用其他方式新开的IE进程则不能共享已经打开的窗口的内存cookie；对于Mozilla Firefox0.8，所有的进程和标签页都可以共享同样的cookie。一般来说是用javascript的window.open打开的窗口会与原窗口共享内存cookie。浏览器对于会话cookie的这种只认cookie不认人的处理方式经常给采用session机制的web应用程序开发者造成很大的困扰。</p>
<p>[经典的语录]</p>
<p>下面就是一个goolge设置cookie的响应头的例子<br />
HTTP/1.1 302 Found<br />
Location: http://www.google.com/intl/zh-CN/<br />
Set-Cookie: PREF=ID=0565f77e132de138:NW=1:TM=1098082649:LM=1098082649:S=KaeaCFPo49RiA_d8; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com<br />
Content-Type: text/html</p>
<p>到时候我们的域就要设置为domain=.*****.cn path=/</p>
<p>session机制是一种服务器端的机制，服务器使用一种类似于散列表的结构（也可能就是使用散列表）来保存信息。</p>
<p>四、理解session机制<br />
session机制是一种服务器端的机制，服务器使用一种类似于散列表的结构（也可能就是使用散列表）来保存信息。</p>
<p>当程序需要为某个客户端的请求创建一个session的时候，服务器首先检查这个客户端的请求里是否已包含了一个session标识 - 称为session id，如果已包含一个session id则说明以前已经为此客户端创建过session，服务器就按照session id把这个session检索出来使用（如果检索不到，可能会新建一个），如果客户端请求不包含session id，则为此客户端创建一个session并且生成一个与此session相关联的session id，session id的值应该是一个既不会重复，又不容易被找到规律以仿造的字符串，这个session id将被在本次响应中返回给客户端保存。</p>
<p>保存这个session id的方式可以采用cookie，这样在交互过程中浏览器可以自动的按照规则把这个标识发挥给服务器。一般这个cookie的名字都是类似于 SEEESIONID，而。比如weblogic对于web应用程序生成的 cookie，JSESSIONID=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764，它的名字就是JSESSIONID。</p>
<p>由于cookie可以被人为的禁止，必须有其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。经常被使用的一种技术叫做URL重写，就是把session id直接附加在URL路径的后面，附加方式也有两种，一种是作为URL路径的附加信息，表现形式为http://..... /xxx;jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764<br />
另一种是作为查询字符串附加在URL后面，表现形式为http://...../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764<br />
这两种方式对于用户来说是没有区别的，只是服务器在解析的时候处理的方式不同，采用第一种方式也有利于把session id的信息和正常程序参数区分开来。<br />
为了在整个交互过程中始终保持状态，就必须在每个客户端可能请求的路径后面都包含这个session id。</p>
<p>另一种技术叫做表单隐藏字段。就是服务器会自动修改表单，添加一个隐藏字段，以便在表单提交时能够把session id传递回服务器。比如下面的表单<br />
&lt;form name="testform" action="/xxx"&gt;<br />
&lt;input type="text"&gt;<br />
&lt;/form&gt;<br />
在被传递给客户端之前将被改写成<br />
&lt;form name="testform" action="/xxx"&gt;<br />
&lt;input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764"&gt;<br />
&lt;input type="text"&gt;<br />
&lt;/form&gt;<br />
这种技术现在已较少应用，笔者接触过的很古老的iPlanet6(SunONE应用服务器的前身)就使用了这种技术。<br />
实际上这种技术可以简单的用对action应用URL重写来代替。</p>
<p>在谈论session机制的时候，常常听到这样一种误解&#8220;只要关闭浏览器，session就消失了&#8221;。其实可以想象一下会员卡的例子，除非顾客主动对店家提出销卡，否则店家绝对不会轻易删除顾客的资料。对session来说也是一样的，除非程序通知服务器删除一个session，否则服务器会一直保留，程序一般都是在用户做log off的时候发个指令去删除session。然而浏览器从来不会主动在关闭之前通知服务器它将要关闭，因此服务器根本不会有机会知道浏览器已经关闭，之所以会有这种错觉，是大部分session机制都使用会话cookie来保存session id，而关闭浏览器后这个session id就消失了，再次连接服务器时也就无法找到原来的session。如果服务器设置的cookie被保存到硬盘上，或者使用某种手段改写浏览器发出的 HTTP请求头，把原来的session id发送给服务器，则再次打开浏览器仍然能够找到原来的session。</p>
<p>恰恰是由于关闭浏览器不会导致session被删除，迫使服务器为seesion设置了一个失效时间，当距离客户端上一次使用session的时间超过这个失效时间时，服务器就可以认为客户端已经停止了活动，才会把session删除以节省存储空间。</p>
<p>[写得太精彩了。感受太深了！]</p>
<p>1、session在何时被创建<br />
一个常见的误解是以为session在有客户端访问时就被创建，然而事实是直到某server端程序调用 HttpServletRequest.getSession(true)这样的语句时才被创建，注意如果JSP没有显示的使用 &lt;%@page session="false"%&gt; 关闭session，则JSP文件在编译成Servlet时将会自动加上这样一条语句HttpSession session = HttpServletRequest.getSession(true);这也是JSP中隐含的session对象的来历。 </p>
<p>由于session会消耗内存资源，因此，如果不打算使用session，应该在所有的JSP中关闭它。</p>
<p>2、session何时被删除<br />
综合前面的讨论，session在下列情况下被删除a.程序调用HttpSession.invalidate();或b.距离上一次收到客户端发送的session id时间间隔超过了session的超时设置;或c.服务器进程被停止（非持久session）</p>
<p>3、如何做到在浏览器关闭时删除session<br />
严格的讲，做不到这一点。可以做一点努力的办法是在所有的客户端页面里使用javascript代码window.oncolose来监视浏览器的关闭动作，然后向服务器发送一个请求来删除session。但是对于浏览器崩溃或者强行杀死进程这些非常规手段仍然无能为力。</p>
<p>7、开两个浏览器窗口访问应用程序会使用同一个session还是不同的session<br />
参见第三小节对cookie的讨论，对session来说是只认id不认人，因此不同的浏览器，不同的窗口打开方式以及不同的cookie存储方式都会对这个问题的答案有影响。</p>
<p>8、如何防止用户打开两个浏览器窗口操作导致的session混乱<br />
这个问题与防止表单多次提交是类似的，可以通过设置客户端的令牌来解决。就是在服务器每次生成一个不同的id返回给客户端，同时保存在session里，客户端提交表单时必须把这个id也返回服务器，程序首先比较返回的id与保存在 session里的值是否一致，如果不一致则说明本次操作已经被提交过了。［对不起你已经投过票了！可以这样来进行控制的哦］</p>
<p>八、总结<br />
session机制本身并不复杂，然而其实现和配置上的灵活性却使得具体情况复杂多变。这也要求我们不能把仅仅某一次的经验或者某一个浏览器，服务器的经验当作普遍适用的经验，而是始终需要具体情况具体分析。</p>
<p><br />
文章出处：DIY部落(http://www.diybl.com/course/3_program/java/javashl/20090306/158662.html)</p>
<p>************************************************************************</p>
<p>关于COOKIE和SESSION的关系，一直没搞清楚。网上一搜COOKIE，普遍都有会话COOKIE和持久COOKIE的概念。 </p>
<p>rubyeye的博客里有这样的解释，我把部分贴过来。（http://rubyeye.javaeye.com/blog/196117） </p>
<p><br />
引用<br />
当你第一次访问一个网站的时候,网站服务器会在响应头内加上<br />
Set-Cookie:PHPSESSID=nj1tvkclp3jh83olcn3191sjq3(php服务器),或Set-Cookie JSESSIONID=nj1tvkclp3jh83olcn3191sjq3(java服务器)信息,此信息是服务器随机生成的,放在服务器内存里,为了标识唯一的客户端用户,内容不会重复,这就是sessionid. <br />
&nbsp;&nbsp; 当浏览器得到这个sessionid会将它放在自己的进程内存里,这里不同的浏览器会有所不同,IE进程间不能共享这个sessionid,也就是新开一个IE将不能共享这个sessionid;而Firefox进程间可以共享.然后你继续发请求给这个网站的时候,浏览器就会把这个sessionid放在请求头里发送给该服务器了,这样服务器得到sessionid后再和自己内存里存放的sessionid对比锁定客户端,从而区分不同客户端,完成会话. <br />
&nbsp;&nbsp; 可以看出如果用这种方式,当用户在会话的过程中关闭浏览器结束进程,则这个sessionid将消失,如果用户又打开浏览器想继续这次会话的时候,就会因为发送的请求中没有这个sessionid而使服务器无法辨别该把那个session信息给他,注意(这个时候服务器端的sessionid和sessionid所指向的session都还存在,只是没有正确的sessionid和它匹配而占用服务器内存,只有session过期或服务器重启才释放内存). <br />
&nbsp;&nbsp; 上面这种方式叫会话cookie,把cookie放在浏览器内存里,只能在这个浏览器的内存范围里完成会话,是一种不长久的方式,为了能长久会话,就出现了持久化cookie,把cookie固化在用户的计算机上,现在的cookie不单单能存放sessionid,还能放用户信息,样式表信息等. <br />
&nbsp;&nbsp; 如果用户禁止了所有cookie的使用,那么会话cookie和持久化cookie都不能用了,有个方案也可以解决问题,就是URL重写,这里要说下的就是URL重写只能实现会话cookie的效果,持久会话实现不了.</p>
<p><br />
刚开始理解时，我也认为会有持久和会话这两种COOKIE。我认为， <br />
会话COOKIE就是用来存放SESSIONID的，并且只存在于浏览器内存，浏览器关闭后会话COOKIE就被删除； <br />
持久COOKIE就是用来存放其它信息，并且是在我们的本地硬盘里能看到的那种COOKIE。 </p>
<p>然后我写了个SERVLET试了一下。 </p>
<p>Java代码 <br />
public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; Cookie cookie = null;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; PrintWriter out = response.getWriter();&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; out.println("&lt;html&gt;&lt;body&gt;");&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; Cookie[] cookies = request.getCookies();&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; // 如果没有COOKIE，新建一个COOKIE&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; if (cookies == null) {&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.println("&lt;b&gt;cookies is null.&lt;/b&gt;&lt;/br&gt;");&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cookie = new Cookie("new", "1");&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; response.addCookie(cookie);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; } else {&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.println("&lt;b&gt;cookies is not null.&lt;/b&gt;&lt;/br&gt;");&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; cookies.length; i++) {&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cookie = cookies[i];&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.println("cookie" + i + " name: " + cookie.getName() + "&lt;/br&gt;");&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; HttpSession session = request.getSession();&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; if (session == null) {&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.println("&lt;b&gt;session is null.&lt;/b&gt;&lt;/br&gt;");&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; } else {&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.println("&lt;b&gt;session is not null.&lt;/b&gt;&lt;/br&gt;");&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.println("session id: " + session.getId() + "&lt;/br&gt;");&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; out.println("&lt;/body&gt;&lt;/html&gt;");&nbsp;&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {<br />
&nbsp;<br />
&nbsp;Cookie cookie = null;<br />
&nbsp;<br />
&nbsp;PrintWriter out = response.getWriter();<br />
&nbsp;out.println("&lt;html&gt;&lt;body&gt;");<br />
&nbsp;<br />
&nbsp;Cookie[] cookies = request.getCookies();<br />
&nbsp;<br />
&nbsp;// 如果没有COOKIE，新建一个COOKIE<br />
&nbsp;if (cookies == null) {<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;out.println("&lt;b&gt;cookies is null.&lt;/b&gt;&lt;/br&gt;");<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;cookie = new Cookie("new", "1");<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;response.addCookie(cookie);<br />
&nbsp;&nbsp;<br />
&nbsp;} else {<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;out.println("&lt;b&gt;cookies is not null.&lt;/b&gt;&lt;/br&gt;");<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;for (int i = 0; i &lt; cookies.length; i++) {<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;cookie = cookies[i];<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;out.println("cookie" + i + " name: " + cookie.getName() + "&lt;/br&gt;");<br />
&nbsp;&nbsp;}<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;HttpSession session = request.getSession();<br />
&nbsp;<br />
&nbsp;if (session == null) {<br />
&nbsp;&nbsp;out.println("&lt;b&gt;session is null.&lt;/b&gt;&lt;/br&gt;");<br />
&nbsp;&nbsp;<br />
&nbsp;} else {<br />
&nbsp;&nbsp;out.println("&lt;b&gt;session is not null.&lt;/b&gt;&lt;/br&gt;");<br />
&nbsp;&nbsp;out.println("session id: " + session.getId() + "&lt;/br&gt;");<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;out.println("&lt;/body&gt;&lt;/html&gt;");<br />
}</p>
<p>第一次访问这个SERVLET，页面显示 </p>
<p>引用<br />
cookies is null. <br />
session is not null. <br />
session id: 0D0AABB6F911362FEE87BEEB2953C33F</p>
<p><br />
第二次访问，页面显示 </p>
<p>引用<br />
cookies is not null. <br />
cookie0 name: new <br />
cookie1 name: JSESSIONID <br />
session is not null. <br />
session id: 0D0AABB6F911362FEE87BEEB2953C33F</p>
<p><br />
第二次访问时从客户端来了两个COOKIE，名为&#8220;new&#8221;的COOKIE是我创建的，名为&#8220;JSESSIONID&#8221;的COOKIE应该是服务器TOMCAT创建的，但这时，在本地硬盘里找不到这两个COOKIE的文件。 </p>
<p>改一下SERVLET，在创建名为&#8220;new&#8221;的COOKIE时，加一句 </p>
<p>Java代码 <br />
cookie.setMaxAge(1000);&nbsp;&nbsp; <br />
cookie.setMaxAge(1000);<br />
然后本地硬盘里就有&#8220;new&#8221;这个COOKIE了。 </p>
<p>这下就有疑问了，在没有设置COOKIE存活期时，自己创建的SESSION不会存到本地硬盘，会不会TOMCAT创建的所谓的会话COOKIE也是没有设置存活期呢？ </p>
<p>然后根据zddava的博客（http://zddava.javaeye.com/blog/311053），找到了TOMCAT里创建会话COOKIE的代码。 <br />
在 <br />
org.apache.catalina.connector.Request.java里， </p>
<p>Java代码 <br />
protected void configureSessionCookie(Cookie cookie) {&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; cookie.setMaxAge(-1);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; String contextPath = null;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; if (!connector.getEmptySessionPath() &amp;&amp; (getContext() != null)) {&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; contextPath = getContext().getEncodedPath();&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; if ((contextPath != null) &amp;&amp; (contextPath.length() &gt; 0)) {&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cookie.setPath(contextPath);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; } else {&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cookie.setPath("/");&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; if (isSecure()) {&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cookie.setSecure(true);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
protected void configureSessionCookie(Cookie cookie) {<br />
&nbsp;&nbsp;&nbsp; cookie.setMaxAge(-1);<br />
&nbsp;&nbsp;&nbsp; String contextPath = null;<br />
&nbsp;&nbsp;&nbsp; if (!connector.getEmptySessionPath() &amp;&amp; (getContext() != null)) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; contextPath = getContext().getEncodedPath();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; if ((contextPath != null) &amp;&amp; (contextPath.length() &gt; 0)) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cookie.setPath(contextPath);<br />
&nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cookie.setPath("/");<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; if (isSecure()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cookie.setSecure(true);<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
cookie.setMaxAge(-1);使COOKIE在浏览器被关闭时删除。而且这里的cookie和上面SERVLET里的cookie都是javax.servlet.http.Cookie。 </p>
<p>由此得出结论:<br />
&nbsp;&nbsp;&nbsp; 可能最开始是我理解错了，COOKIE并没有会话COOKIE和持久COOKIE之分。我们本地创建的&#8220;持久COOKIE&#8221;和WEB容器创建的&#8220;会话COOKIE&#8221;都是一种COOKIE，就是javax.servlet.http.Cookie。只是WEB容器把存活期设置成了关闭浏览器时删除而已（TOMCAT）。<br />
&nbsp;&nbsp;&nbsp; 这个结论不正确。在服务器端设置过期时间后就是持久cookie了，所以有会话COOKIE和持久COOKIE之分。<br />
************************************************************************<br />
cookie和session机制之间的区别与联系 <br />
具体来说cookie机制采用的是在客户端保持状态的方案。它是在用户端的会话状态的存贮机制，他需要用户打开客户端的cookie支持。cookie的作用就是为了解决HTTP协议无状态的缺陷所作的努力.<br />
而session机制采用的是一种在客户端与服务器之间保持状态的解决方案。同时我们也看到，由于采用服务器端保持状态的方案在客户端也需要保存一个标识，所以session机制可能需要借助于cookie机制来达到保存标识的目的。而session提供了方便管理全局变量的方式<br />
session是针对每一个用户的，变量的值保存在服务器上，用一个sessionID来区分是哪个用户session变量,这个值是通过用户的浏览器在访问的时候返回给服务器，当客户禁用cookie时，这个值也可能设置为由get来返回给服务器。<br />
就安全性来说：当你访问一个使用session 的站点，同时在自己机子上建立一个cookie，建议在服务器端的SESSION机制更安全些.因为它不会任意读取客户存储的信息。</p>
<p>正统的cookie分发是通过扩展HTTP协议来实现的，服务器通过在HTTP的响应头中加上一行特殊的指示以提示浏览器按照指示生成相应的cookie<br />
从网络服务器观点看所有HTTP请求都独立于先前请求。就是说每一个HTTP响应完全依赖于相应请求中包含的信息<br />
状态管理机制克服了HTTP的一些限制并允许网络客户端及服务器端维护请求间的关系。在这种关系维持的期间叫做会话(session)。<br />
Cookies是服务器在本地机器上存储的小段文本并随每一个请求发送至同一个服务器。IETF RFC 2965 HTTP State Management Mechanism 是通用cookie规范。网络服务器用HTTP头向客户端发送cookies，在客户终端，浏览器解析这些cookies并将它们保存为一个本地文件，它会自动将同一服务器的任何请求缚上这些cookies<br />
-------------------------------------------------------------------------------------------------------------------------------------------------------------------<br />
理解session机制<br />
session机制是一种服务器端的机制，服务器使用一种类似于散列表的结构（也可能就是使用散列表）来保存信息。</p>
<p>当程序需要为某个客户端的请求创建一个session的时候，服务器首先检查这个客户端的请求里是否已包含了一个session标识 - 称为 session id，如果已包含一个session id则说明以前已经为此客户端创建过session，服务器就按照session id把这个 session检索出来使用（如果检索不到，可能会新建一个），如果客户端请求不包含session id，则为此客户端创建一个session并且生成一个与此session相关联的session id，session id的值应该是一个既不会重复，又不容易被找到规律以仿造的字符串，这个 session id将被在本次响应中返回给客户端保存。</p>
<p>保存这个session id的方式可以采用cookie，这样在交互过程中浏览器可以自动的按照规则把这个标识发挥给服务器。一般这个cookie的名字都是类似于SEEESIONID，而。比如weblogic对于web应用程序生成的cookie，JSESSIONID= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764，它的名字就是 JSESSIONID。</p>
<p>由于cookie可以被人为的禁止，必须有其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。经常被使用的一种技术叫做URL重写，就是把session id直接附加在URL路径的后面，附加方式也有两种，一种是作为URL路径的附加信息，表现形式为http://...../xxx;jsessionid= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764<br />
另一种是作为查询字符串附加在URL后面，表现形式为http://...../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764<br />
这两种方式对于用户来说是没有区别的，只是服务器在解析的时候处理的方式不同，采用第一种方式也有利于把session id的信息和正常程序参数区分开来。<br />
为了在整个交互过程中始终保持状态，就必须在每个客户端可能请求的路径后面都包含这个session id。</p>
<p>另一种技术叫做表单隐藏字段。就是服务器会自动修改表单，添加一个隐藏字段，以便在表单提交时能够把session id传递回服务器。比如下面的表单<br />
&lt;form name="testform" action="/xxx"&gt;<br />
&lt;input type="text"&gt;<br />
&lt;/form&gt;<br />
在被传递给客户端之前将被改写成<br />
&lt;form name="testform" action="/xxx"&gt;<br />
&lt;input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764"&gt;<br />
&lt;input type="text"&gt;<br />
&lt;/form&gt;<br />
这种技术现在已较少应用，笔者接触过的很古老的iPlanet6(SunONE应用服务器的前身)就使用了这种技术。<br />
实际上这种技术可以简单的用对action应用URL重写来代替。</p>
<p>在谈论session机制的时候，常常听到这样一种误解&#8220;只要关闭浏览器，session就消失了&#8221;。其实可以想象一下会员卡的例子，除非顾客主动对店家提出销卡，否则店家绝对不会轻易删除顾客的资料。对session来说也是一样的，除非程序通知服务器删除一个session，否则服务器会一直保留，程序一般都是在用户做log off的时候发个指令去删除session。然而浏览器从来不会主动在关闭之前通知服务器它将要关闭，因此服务器根本不会有机会知道浏览器已经关闭，之所以会有这种错觉，是大部分session机制都使用会话cookie来保存session id，而关闭浏览器后这个 session id就消失了，再次连接服务器时也就无法找到原来的session。如果服务器设置的cookie被保存到硬盘上，或者使用某种手段改写浏览器发出的HTTP请求头，把原来的session id发送给服务器，则再次打开浏览器仍然能够找到原来的session。</p>
<p>恰恰是由于关闭浏览器不会导致session被删除，迫使服务器为seesion设置了一个失效时间，当距离客户端上一次使用session的时间超过这个失效时间时，服务器就可以认为客户端已经停止了活动，才会把session删除以节省存储空间。<br />
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------<br />
&nbsp;由JSESSIONID谈cookie与SESSION的区别和联系 <br />
在一些投票之类的场合，我们往往因为公平的原则要求每人只能投一票，在一些WEB开发中也有类似的情况，这时候我们通常会使用COOKIE来实现，例如如下的代码：<br />
&lt; % cookie[]cookies = request.getCookies();<br />
if (cookies.lenght == 0 || cookies == null)<br />
doStuffForNewbie();<br />
//没有访问过 <br />
}</p>
<p>else<br />
{<br />
doStuffForReturnVisitor(); //已经访问过了<br />
}</p>
<p>% &gt;</p>
<p>这是很浅显易懂的道理，检测COOKIE的存在，如果存在说明已经运行过写入COOKIE的代码了，然而运行以上的代码后，无论何时结果都是执行doStuffForReturnVisitor()，通过控制面板-Internet选项-设置-察看文件却始终看不到生成的cookie文件，奇怪，代码明明没有问题，不过既然有cookie，那就显示出来看看。<br />
cookie[]cookies = request.getCookies();<br />
if (cookies.lenght == 0 || cookies == null)<br />
out.println("Has not visited this website");<br />
}</p>
<p>else<br />
{<br />
for (int i = 0; i &lt; cookie.length; i++)<br />
{<br />
out.println("cookie name:" + cookies[i].getName() + "cookie value:" +<br />
cookie[i].getValue());<br />
}<br />
}</p>
<p>运行结果:<br />
cookie name:JSESSIONID cookie value:KWJHUG6JJM65HS2K6 为什么会有cookie呢,大家都知道，http是无状态的协议，客户每次读取web页面时，服务器都打开新的会话，而且服务器也不会自动维护客户的上下文信息，那么要怎么才能实现网上商店中的购物车呢，session就是一种保存上下文信息的机制，它是针对每一个用户的，变量的值保存在服务器端，通过SessionID来区分不同的客户,session是以cookie或URL重写为基础的，默认使用cookie来实现，系统会创造一个名为JSESSIONID的输出cookie，我们叫做session cookie,以区别persistent cookies,也就是我们通常所说的cookie,注意session cookie是存储于浏览器内存中的，并不是写到硬盘上的，这也就是我们刚才看到的JSESSIONID，我们通常情是看不到JSESSIONID的，但是当我们把浏览器的cookie禁止后，web服务器会采用URL重写的方式传递Sessionid，我们就可以在地址栏看到sessionid=KWJHUG6JJM65HS2K6之类的字符串。<br />
明白了原理，我们就可以很容易的分辨出persistent cookies和session cookie的区别了，网上那些关于两者安全性的讨论也就一目了然了，session cookie针对某一次会话而言，会话结束session cookie也就随着消失了，而persistent cookie只是存在于客户端硬盘上的一段文本（通常是加密的），而且可能会遭到cookie欺骗以及针对cookie的跨站脚本攻击，自然不如session cookie安全了。<br />
通常session cookie是不能跨窗口使用的，当你新开了一个浏览器窗口进入相同页面时，系统会赋予你一个新的sessionid，这样我们信息共享的目的就达不到了，此时我们可以先把sessionid保存在persistent cookie中，然后在新窗口中读出来，就可以得到上一个窗口SessionID了，这样通过session cookie和persistent cookie的结合我们就实现了跨窗口的session tracking（会话跟踪）。<br />
在一些web开发的书中，往往只是简单的把Session和cookie作为两种并列的http传送信息的方式，session cookies位于服务器端，persistent cookie位于客户端，可是session又是以cookie为基础的，明白的两者之间的联系和区别，我们就不难选择合适的技术来开发web service了。</p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，http://blog.csdn.net/yuhua3272004/archive/2009/07/17/4357268.aspx</p>
<img src ="http://www.blogjava.net/freeman1984/aggbug/331501.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/freeman1984/" target="_blank">疯狂</a> 2010-09-09 13:26 <a href="http://www.blogjava.net/freeman1984/archive/2010/09/09/331501.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>探讨JavaClassLoader与Package机制</title><link>http://www.blogjava.net/freeman1984/archive/2010/09/01/330647.html</link><dc:creator>疯狂</dc:creator><author>疯狂</author><pubDate>Wed, 01 Sep 2010 15:12:00 GMT</pubDate><guid>http://www.blogjava.net/freeman1984/archive/2010/09/01/330647.html</guid><wfw:comment>http://www.blogjava.net/freeman1984/comments/330647.html</wfw:comment><comments>http://www.blogjava.net/freeman1984/archive/2010/09/01/330647.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/freeman1984/comments/commentRss/330647.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/freeman1984/services/trackbacks/330647.html</trackback:ping><description><![CDATA[文章转自：http://blog.csdn.net/Senton/archive/2007/10/03/1810766.aspx<br />
<p>为了深入了解Java的ClassLoader机制，我们先来做以下实验：</p>
<p>package java.lang;<br />
public class Test {<br />
&nbsp;&nbsp;&nbsp; public static void main(String[] args) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char[] c = "1234567890".toCharArray();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String s = new String(0, 10, c);<br />
&nbsp;&nbsp;&nbsp; }<br />
}</p>
<p>String类有一个Package权限的构造函数String(int offset, int length, char[] array)，按照默认的访问权限，由于Test属于java.lang包，因此理论上应该可以访问String的这个构造函数。编译通过！执行时结果如下：</p>
<p>Exception in thread "main" java.lang.SecurityException: Prohibited package name:<br />
&nbsp;java.lang<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.ClassLoader.defineClass(Unknown Source)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.security.SecureClassLoader.defineClass(Unknown Source)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.net.URLClassLoader.defineClass(Unknown Source)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.net.URLClassLoader.access$100(Unknown Source)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.net.URLClassLoader$1.run(Unknown Source)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.security.AccessController.doPrivileged(Native Method)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.net.URLClassLoader.findClass(Unknown Source)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.ClassLoader.loadClass(Unknown Source)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.ClassLoader.loadClass(Unknown Source)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at java.lang.ClassLoader.loadClassInternal(Unknown Source)</p>
<p>奇怪吧？要弄清为什么会有SecurityException，就必须搞清楚ClassLoader的机制。</p>
<p>Java的ClassLoader就是用来动态装载class的，ClassLoader对一个class只会装载一次，JVM使用的ClassLoader一共有4种：</p>
<p>启动类装载器，标准扩展类装载器，类路径装载器和网络类装载器。</p>
<p>这4种ClassLoader的优先级依次从高到低，使用所谓的&#8220;双亲委派模型&#8221;。 确切地说，如果一个网络类装载器被请求装载一个java.lang.Integer，它会首先把请求发送给上一级的类路径装载器，如果返回已装载，则网络 类装载器将不会装载这个java.lang.Integer，如果上一级的类路径装载器返回未装载，它才会装载java.lang.Integer。</p>
<p>类 似的，类路径装载器收到请求后（无论是直接请求装载还是下一级的ClassLoader上传的请求），它也会先把请求发送到上一级的标准扩展类装载器，这 样一层一层上传，于是启动类装载器优先级最高，如果它按照自己的方式找到了java.lang.Integer，则下面的ClassLoader 都不能再装载java.lang.Integer，尽管你自己写了一个java.lang.Integer，试图取代核心库的 java.lang.Integer是不可能的，因为自己写的这个类根本无法被下层的ClassLoader装载。</p>
<p>再说说Package权限。Java语言规定，在同一个包中的class，如果没有修饰符，默认为Package权限，包内的class都可以访问。但是这还不够准确。确切的说，只有由同一个ClassLoader装载的class才具有以上的Package权限。比如启动类装载器装载了java.lang.String，类路径装载器装载了我们自己写的java.lang.Test，它们不能互相访问对方具有Package权限的方法。这样就阻止了恶意代码访问核心类的Package权限方法。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/freeman1984/aggbug/330647.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/freeman1984/" target="_blank">疯狂</a> 2010-09-01 23:12 <a href="http://www.blogjava.net/freeman1984/archive/2010/09/01/330647.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>md5加盐验证用户密码的小例子</title><link>http://www.blogjava.net/freeman1984/archive/2010/02/09/312406.html</link><dc:creator>疯狂</dc:creator><author>疯狂</author><pubDate>Tue, 09 Feb 2010 05:13:00 GMT</pubDate><guid>http://www.blogjava.net/freeman1984/archive/2010/02/09/312406.html</guid><wfw:comment>http://www.blogjava.net/freeman1984/comments/312406.html</wfw:comment><comments>http://www.blogjava.net/freeman1984/archive/2010/02/09/312406.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/freeman1984/comments/commentRss/312406.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/freeman1984/services/trackbacks/312406.html</trackback:ping><description><![CDATA[<p>package com.test;</p>
<p>import java.io.ByteArrayOutputStream;<br />
import java.io.File;<br />
import java.io.FileInputStream;<br />
import java.io.FileOutputStream;<br />
import java.nio.ByteBuffer;<br />
import java.nio.channels.FileChannel;<br />
import java.security.MessageDigest;<br />
import java.security.SecureRandom;<br />
import java.util.Arrays;</p>
<p>//使用md5和盐验证安全登陆<br />
public class Test_MD5 {</p>
<p>&nbsp;private static final String PWD_FILE = "c:\\pwd.txt"; <br />
&nbsp;/**<br />
&nbsp; * @param args<br />
&nbsp; */<br />
&nbsp;public static void main(String[] args) throws Exception{<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;//用户创建密码，服务端杂凑并保存<br />
&nbsp;&nbsp;saveMessagePwdInFile("admin");<br />
&nbsp;&nbsp;////验证用户输入<br />
&nbsp;&nbsp;checkUserPwd("admin1");<br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;<br />
&nbsp;}<br />
&nbsp;public static void saveMessagePwdInFile(String inputPwd)throws Exception{<br />
&nbsp;&nbsp;byte[] salt = new byte[8];<br />
&nbsp;&nbsp;SecureRandom random = new SecureRandom();<br />
&nbsp;&nbsp;random.nextBytes(salt);<br />
&nbsp;&nbsp;System.out.println("生成的盐："+Arrays.toString(salt));<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;MessageDigest digest = MessageDigest.getInstance("MD5");//当然可以使用SHA（160位），MD5(128位)<br />
&nbsp;&nbsp;digest.update(salt);<br />
&nbsp;&nbsp;digest.update(inputPwd.getBytes("utf-8"));<br />
&nbsp;&nbsp;byte[] afterMd5 = digest.digest();<br />
&nbsp;&nbsp;System.out.println("杂凑值："+Arrays.toString(afterMd5));<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;//盐和杂凑值写入文件<br />
&nbsp;&nbsp;FileOutputStream outputStream = new FileOutputStream(new File(PWD_FILE));<br />
&nbsp;&nbsp;FileChannel channel = outputStream.getChannel();<br />
&nbsp;&nbsp;channel.write(ByteBuffer.wrap(salt));<br />
&nbsp;&nbsp;channel.write(ByteBuffer.wrap(afterMd5));<br />
&nbsp;&nbsp;outputStream.flush();<br />
&nbsp;&nbsp;outputStream.close();<br />
&nbsp;&nbsp;System.out.println("保存信息完毕...");<br />
&nbsp;&nbsp;<br />
&nbsp;}<br />
&nbsp;public static void checkUserPwd(String pwd)throws Exception{<br />
&nbsp;&nbsp;ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();<br />
&nbsp;&nbsp;FileInputStream fileInputStream = new FileInputStream(new File(PWD_FILE));<br />
&nbsp;&nbsp;FileChannel channel2 = fileInputStream.getChannel();<br />
&nbsp;&nbsp;ByteBuffer dst = ByteBuffer.allocate(1024);<br />
&nbsp;&nbsp;int l = -1;<br />
&nbsp;&nbsp;while((l=channel2.read(dst))!=-1){<br />
&nbsp;&nbsp;&nbsp;dst.flip();<br />
&nbsp;&nbsp;&nbsp;byteArrayOutputStream.write(dst.array(),0,l);<br />
&nbsp;&nbsp;&nbsp;dst.compact();<br />
&nbsp;&nbsp;&nbsp;dst.clear();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;fileInputStream.close();<br />
&nbsp;&nbsp;byte[] pwdbyte = byteArrayOutputStream.toByteArray();<br />
&nbsp;&nbsp;byteArrayOutputStream.reset();<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;byte[] salt2 = new byte[8];<br />
&nbsp;&nbsp;System.arraycopy(pwdbyte, 0, salt2, 0, 8);<br />
&nbsp;&nbsp;System.out.println("从文件获取盐："+Arrays.toString(salt2));<br />
&nbsp;&nbsp;byte[] pwdinfile = new byte[pwdbyte.length-8];<br />
&nbsp;&nbsp;System.arraycopy(pwdbyte, 8, pwdinfile, 0, pwdbyte.length-8);<br />
&nbsp;&nbsp;System.out.println("从文件获取杂凑值："+Arrays.toString(pwdinfile));<br />
&nbsp;&nbsp;&nbsp;&nbsp; byte[] toyz = getUserMd5Pwd(salt2,pwd);<br />
&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(Arrays.equals(toyz, pwdinfile)==true?"登陆成功":"密码有误，登录失败...");<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;&nbsp; public static byte[] getUserMd5Pwd(byte[] salt,String pwd) throws Exception{<br />
&nbsp;&nbsp;&nbsp; MessageDigest digest2 = MessageDigest.getInstance("MD5");<br />
&nbsp;&nbsp;digest2.update(salt);<br />
&nbsp;&nbsp;&nbsp;&nbsp; digest2.update(pwd.getBytes("utf-8"));<br />
&nbsp;&nbsp;&nbsp;&nbsp; byte[] toyz = digest2.digest();<br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("用户输入杂凑值："+Arrays.toString(toyz));<br />
&nbsp;&nbsp;&nbsp;&nbsp; return toyz;<br />
&nbsp;&nbsp; }<br />
}<br />
</p>
<img src ="http://www.blogjava.net/freeman1984/aggbug/312406.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/freeman1984/" target="_blank">疯狂</a> 2010-02-09 13:13 <a href="http://www.blogjava.net/freeman1984/archive/2010/02/09/312406.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>