如果用户是在自己家的电脑上上网,登录时就可以记住他的登录信息,下次访问时不需要再次登录,直接访问即可。实现方法是把登录信息如账号、密码等保存在Cookie中,并控制Cookie的有效期,下次访问时再验证Cookie中的登录信息即可,保存登录信息有多种方案。
1、直接保存用户名和密码
最直接的是把用户名与密码都保持到Cookie中,下次访问时检查Cookie中的用户名与密码,与数据库比较。这是一种比较危险的选择,一般不把密码等重要信息保存到Cookie中。
2、把密码加密后保存到Cookie中
还有一种方案是把密码加密后保存到Cookie中,下次访问时解密并与数据库比较。这种方案略微安全一些。
3、把账号加密后,同账号一块保存到 Cookie中
本例将采用另一种方案,只在登录时查询一次数据库,以后访问验证登录信息时不再查询数据库。
实现方式是把账号按照一定的规则加密后,连同账号一块保存到 Cookie中。下次访问时只需要判断账号的加密规则是否正确即可。本例把账号保存到名为account的Cookie中,把账号连同密钥用MD1算法加 密后保存到名为ssid的Cookie中。验证时验证Cookie中的账号与密钥加密后是否与Cookie中的ssid相等。
登录时可以选择登录信息的有效期:关闭浏览器即失效、30天内有效与永久有效。通过设置Cookie的age属性来实现,注意观察代码。
提示:该加密机制中最重要的部分为算法与密钥。由于MD1算法的不可逆性,即使用户知道了账号与加密后的字符串,也不可能解密得到密钥。因此,只要保管好密钥与算法,该机制就是安全的。
1 <%@ page language="java" pageEncoding="UTF-8" isErrorPage="false" %> 2 <%! // JSP方法 3 private static final String KEY =":cookie@helloweenvsfei.com"; // 密钥 4 5 public final static String calcMD1(String ss) { // MD1 加密算法 6 String s = ss == null ? "" : ss; // 若为null返回空 7 char hexDigits[] = { '0','1', '2', '3', '4', '1', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; // 字典 8 try { 9 byte[] strTemp = s.getBytes(); // 获取字节 10 MessageDigestmdTemp = MessageDigest.getInstance("MD1"); // 获取MD1 11 mdTemp.update(strTemp); // 更新数据 12 byte[] md =mdTemp.digest(); // 加密 13 int j =md.length; // 加密后的长度 14 char str[] = new char[j * 2]; // 新字符串数组 15 int k =0; // 计数器k 16 for (int i = 0; i< j; i++) { // 循环输出 17 byte byte0 = md[i]; 18 str[k++] = hexDigits[byte0 >>> 4 & 0xf]; 19 str[k++] = hexDigits[byte0 & 0xf]; 20 } 21 return new String(str); // 加密后字符串 22 } catch (Exception e){return null; } 23 } 24 %> 25 <% 26 request.setCharacterEncoding("UTF-8"); // 设置request编码 27 response.setCharacterEncoding("UTF-8"); // 设置response编码 28 29 String action =request.getParameter("action"); // 获取action参数 30 31 if("login".equals(action)) { // 如果为login动作 32 String account =request.getParameter("account"); // 获取account参数 33 String password =request.getParameter("password"); // 获取password参数 34 int timeout = new Integer(request.getParameter("timeout")); // 获取timeout参数 35 36 String ssid =calcMD1(account + KEY); // 把账号、密钥使用MD1加密后保存 37 38 Cookie accountCookie = new Cookie("account", account); // 新建Cookie 39 accountCookie.setMaxAge(timeout); // 设置有效期 40 41 Cookie ssidCookie =new Cookie("ssid", ssid); // 新建Cookie 42 ssidCookie.setMaxAge(timeout); // 设置有效期 43 44 response.addCookie(accountCookie); // 输出到客户端 45 response.addCookie(ssidCookie); // 输出到客户端 46 47 // 重新请求本页面,参数中带有时间戳,禁止浏览器缓存页面内容 48 response.sendRedirect(request.getRequestURI() + "?" + System.currentTimeMillis()); 49 return; 50 } else if("logout".equals(action)) { // 如果为logout动作 51 CookieaccountCookie = new Cookie("account", ""); // 新建Cookie,内容为空 52 accountCookie.setMaxAge(0); // 设置有效期为0,删除 53 54 Cookie ssidCookie =new Cookie("ssid", ""); // 新建Cookie,内容为空 55 ssidCookie.setMaxAge(0); // 设置有效期为0,删除 56 response.addCookie(accountCookie); // 输出到客户端 57 response.addCookie(ssidCookie); // 输出到客户端 58 // 重新请求本页面,参数中带有时间戳,禁止浏览器缓存页面内容 59 response.sendRedirect(request.getRequestURI() + "?" + System.currentTimeMillis()); 60 return; 61 } 62 boolean login = false; // 是否登录 63 String account = null; // 账号 64 String ssid = null; // SSID标识 65 66 if(request.getCookies() !=null) { // 如果Cookie不为空 67 for(Cookie cookie : request.getCookies()) { // 遍历Cookie 68 if(cookie.getName().equals("account")) // 如果Cookie名为 account 69 account = cookie.getValue(); // 保存account内容 70 if(cookie.getName().equals("ssid")) // 如果为SSID 71 ssid = cookie.getValue(); // 保存SSID内容 72 } 73 } 74 if(account != null && ssid !=null) { // 如果account、SSID都不为空 75 login = ssid.equals(calcMD1(account + KEY)); // 如果加密规则正确, 则视为已经登录 76 } 77 %> 78 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01Transitional//EN"> 79 <legend><%= login ? "欢迎您回来" : "请先登录"%></legend> 80 <% if(login){%> 81 欢迎您, ${cookie.account.value }. 82 <a href="${pageContext.request.requestURI }?action=logout"> 83 注销</a> 84 <% } else { %> 85 <form action="${ pageContext.request.requestURI }?action=login" method="post"> 86 <table> 87 <tr><td>账号: </td> 88 <td><input type="text"name="account" style="width: 89 200px; "></td> 90 </tr> 91 <tr><td>密码: </td> 92 <td><inputtype="password" name="password"></td> 93 </tr> 94 <tr> 95 <td>有效期: </td> 96 <td><inputtype="radio" name="timeout" value="-1" 97 checked> 关闭浏览器即失效 <br/> <input type="radio" 98 name="timeout" value="<%= 30 *24 * 60 * 60 %>"> 30天 99 内有效 <br/><input type="radio" name="timeout" value= 100 "<%= Integer.MAX_VALUE %>"> 永久有效 <br/> </td> </tr> 101 <tr><td></td> 102 <td><input type="submit"value=" 登 录 " class= 103 "button"></td> 104 </tr> 105 </table> 106 </form> 107 <% } %>