使用Session和Cookie实现网站自动登录
登陆的时候一旦选择了[自动登录]的选项,则需要在登陆成功后,附加下面的代码
应为一般网站都提供保存用户名的功能,所以我把这个写到了外面。只有密码是单独处理的。
其中的host就是你的域名。
第一步,编写login.jsp文件,内容如下:
本部分设定了隐藏,您已回复过了,以下是隐藏的内容
String host = request.getServerName();
Cookie cookie = new Cookie("SESSION_LOGIN_USERNAME", username); // 保存用户名到Cookie
cookie.setPath("/");
cookie.setDomain(host);
cookie.setMaxAge(99999999);
response.addCookie(cookie);
if (ParamUtils.getBooleanParameter(request, "savePassword")) {
// 保存密码到Cookie,注意需要加密一下
cookie = new Cookie("SESSION_LOGIN_PASSWORD", MD5.encode(u.getPassword()));
cookie.setPath("/");
cookie.setDomain(host);
cookie.setMaxAge(99999999);
response.addCookie(cookie);
}
这样,Cookie就生成了
第二步,在用户访问网站的时候,如果检测到没有登陆,则进行下面的判断,
例如编写一个index.jsp,内容如下:
String usernameCookie = null;
String passwordCookie = null;
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if ("SESSION_LOGIN_USERNAME".equals(cookie.getName())) {
usernameCookie = cookie.getValue(); // 得到cookie的用户名
}
if ("SESSION_LOGIN_PASSWORD".equals(cookie.getName())) {
passwordCookie = cookie.getValue(); // 得到cookie的密码
}
}
if (usernameCookie != null && passwordCookie != null) { // 如果存在
if(Login.checkLogin(usernameCookie ,passwordCookie)){
// 登陆成功的处理
}else{
// 登陆不成功的处理
}
}
}
这部份代码可以写到action或servlet中。最后一个注意事项,应该在退出登录里面清除cookie,以免他无法换账号登陆了!
logout.jsp内容如下:
cookie = new Cookie("SESSION_LOGIN_PASSWORD", "");
cookie.setPath("/");
cookie.setMaxAge(99999999);
cookie.setDomain(host);
response.addCookie(cookie);
注意事项:
一旦自动登录失败,则取消其自动登录的可能性,防止暴力破解! 所以通常会在对应的实体中定义一个属性来标示是否自动登录,也就是说:这个标志只有下次正常输入验证码的登陆才会被清除!!
jsp使用cookie实现自动登录
一、什么是用户自动登录?
对于我们的网站向已注册用户提供某些专门的服务,比如网上购物、在线下载、收费浏览等等,就会要求用户在使用这些服务之前进入登录页面,输入用户名和密码,并进行验证。
如果用户经常访问我们的网站,假如每天都访问一次,或者好几次,那么用户每次都重复这些登录操作就会感到相当厌烦。通过一些简单的技术手段,我们可以让网站“记住”那些在曾经登录过的用户。当该用户下次再来访问的时候,网站可以识别该用户,并为其自动完成登录过程。
二、基本思路
作为网站的编写者,我们无从知道坐在电脑前的那个人是谁。我们能够知道的是,访问网站的是哪一台电脑——这一点可以通过Cookie实现。因此,对用户的识别实际上就是对客户端电脑的识别。
简单的说,当用户第一次登录网站的时候,网站向客户端发送一个包含有用户名的Cookie。当用户在之后的某个时候再次访问,浏览器就会向网站服务器回送这个Cookie,于是,我们可以从这个Cookie中读取到用户名,然后调用登录的方法,从而实现自动为用户登录。
三、防止欺骗
Cookie只是一个普通的文本文件,那里面包含的字符串可以直接用记事本打开并进行编辑。因此任何人在任何电脑上都可以伪造一个包含有他人用户名 的 Cookie,
从而实现对他人身份的冒用。要解决这个问题,就要在Cookie中附加一项信息,这个信息需要具有以下特性:
1、和该用户一一对应;2、伪 造难度大。这些内容和用户名一起,以Cookie的形式发送给用户的浏览器。
并且,服务器必须能够记住这项内容,以便用户再次访问的时候进行核对。
理论上,可以使用该用户的密码。密码具备了前述的两个特点。但是因为Cookie本身未经加密,保存于其中的密码(应该加密)可以被任何人看到,因此这个方法极不安全。
另一种可以加以利用的信息是用户访问时的Session id。因为Session id是一个由系统随机产生的、无规律的、长度较长的字符串,因此它很难被伪造。
要把它和用户对应起来,我们需要在数据库中添加一个表,这个表至少有两个字 段,一个是用户名,一个是Session id。
当用户首次登录的时候,我们把当前的Session id和用户名分别用Cookie发送给用户,同时,把这两项作为一条记录插入数据库。
这样,当用户再次访问的时候,服务器就可以读取客户端发来的这两个 Cookie,并且用它们的值和数据库中的记录比对。
如果在数据库中找到了相应记录,就说明这台电脑的确是该用户上次登录时使用的电脑,进而可以为该用户自动登录。
四、实现
1、在登录页面中添加一个复选框,让用户选择是否愿意在一定时间内实现自动登陆,例如两周。
代码:
<input type="checkbox" name="autologin">两周内自动登录
2、在负责处理登录过程的Servlet中,判断用户是否选择了该复选框。如果是,则执行这两个操作:向用户发送两个Cookie,以及向数据库写入一条相应的记录。
代码:
Cookie ckUsername, ckSessionid;
if (autologin.equals("on")) {
// 如果用户选择了“两周内自动登录”,则向用户发送两个cookie。
// 一个cookie记录用户名,另一个记录唯一的验证码,
// 并将此验证码写入数据库,以备用户返回时查询。(防止伪造cookie)
ckUsername = new Cookie("autoLoginUser", user.getUsername()); // user是代表用户的bean
ckUsername.setMaxAge(60 * 60 * 24 * 14); //设置Cookie有效期为14天
res.addCookie(ckUsername);
sessionid = session.getId(); // 取得当前的session id
ckSessionid = new Cookie("sessionid", sessionid);
ckSessionid.setMaxAge(60 * 60 * 24 * 14);
res.addCookie(ckSessionid);
// 在数据库中插入相应记录
userSessionDAO.insertUserSession(user, sessionid);
}
3、实现自动登录。因为用户下次访问的时候,可能直接访问网站的任何页面(例如通过收藏夹),而不一定是首页或者登录页面,
所以我们需要用Filter拦截到达该网站的所有请求,并执行自动登录。
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpSession session = request.getSession(true);
String username;
String sessionid; // 此sessionid是上次用户登录时保存于用户端的识别码,用于用户后续访问的自动登录。不是本次访问的session id。
Cookie[] cookies;
CookieManager cm = new CookieManager(); // CookieManager是一个自定义的类,用于从Cookie数组中查找并返回指定名称的Cookie值。
boolean isAutoLogin;
// 如果session中没有user对象,则创建一个。
User user = (User) session.getAttribute("user");
if (user == null) {
user = new User(); // 此时user中的username属性为"",表示用户未登录。
}
// 如果user对象的username为"",表示用户未登录。则执行自动登录过程。
// 否则不自动登录。
if (user.getUsername().equals("")) {
// 检查用户浏览器是否发送了上次登录的用户名和sessionid,
// 如果是,则为用户自动登陆。
cookies = request.getCookies();
username = cm.getCookieValue(cookies, "autoLoginUser");
sessionid = cm.getCookieValue(cookies, "sessionid");
isAutoLogin = userSessionDAO.getAutoLoginState(username, sessionid); // 如果在数据库中找到了相应记录,则说明可以自动登录。
if (isAutoLogin) {
user.setUsername(username);
user.setNickname(DBUtil.getNickName(username));
session.setAttribute("user", user); // 将user bean添加到session中。
}
}
chain.doFilter(req, resp);
}
4、注销。只有当用户在上次访问时,未经注销就离开网站,我们才能在该用户下次访问时执行自动登录。如果用户显式的执行了注销操作,那就表示该用户 不希望我们记住他。我们需要在执行注销操作的Servlet中,从数据库中删除相应记录。这样,下次用户访问的时候就不会执行自动登录了。
五、改进
用户可能为了方便,自行修改Cookie中的有效期,从而达到长期自动登录的目的。对某些存有敏感信息的网站来说,这样做并不安全。当用户长时间没有使用他的电脑,或者将电脑遗弃、转让了,而保存于其中的Cookie仍然是有效的,这就为用户和网站带来潜在的风险。
要解决这个问题,我们可以在数据库中增加一个字段,用以记录自动登录的过期日。这样,是否执行自动登录就不再以客户端的Cookie有效期为准,而 是以服务器端数据库中的信息为准。当我们想要调整用户自动登录的有效期的时候,只需要修改数据库中相应的日期字段即可,因而这一过程变得更加安全。
1.用到的常量
Java代码
package com.hydom.util;
public final class CommonConstants {
// 系统 session 用户
public final static String SESSION_USER = "session_user";
/** 保存在浏览器中cookie的邮箱名称名 */
public final static String BROWSER_COOKIE_EMAIL = "HKPhotoUserEmail";
/** 保存在浏览器中cookie的邮箱密码名 */
public final static String BROWSER_COOKIE_PASSWORD = "HKPhotoUserPassword";
/** 保存在浏览器中cookie的最大时间15天 */
public final static int BROWSER_COOKIE_MAX_AGE = 15*24*60*60;
/** 保存在浏览器中cookie的自动登录状态名 */
public final static String BROWSER_COOKIE_AUTO_STATUS_NAME = "HKPhotoAutoLoginStatus";
/** 保存在浏览器中cookie的退出登录名 */
public final static String BROWSER_COOKIE_LOGIN_OUT_NAME = "HKPhotoLoginOut";
}
2.过滤器
Java代码
package com.hydom.filter;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.hydom.entity.User;
import com.hydom.service.IUserService;
import com.hydom.util.CommonConstants;
import com.hydom.util.pico.PicoContainer;
/**
*功能:首先检测session中是否有user,如果没有再检测cookie中是否有对应的邮箱和密码<BR>
* 如果有那么就查出该user放进session中<BR>
* 如果都没有那么就doFilter()<BR>
*
* @author ocaicai@yeah.net<BR>
* @date 2011-9-22<BR>
* @version 1.0 <BR>
*
*/
public class CookieLoginFilter extends BaseFilter {
// 获取数据层示例
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
Object object = request.getSession().getAttribute(
CommonConstants.SESSION_USER);
User cookieUser = null;
String email = null;
String password = null;
String autoStatus = null;
if (object == null) {
Cookie[] cookies = request.getCookies();
if (cookies != null && cookies.length > 0) {
// System.out.println("cookies.length=" + cookies.length);
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
// 判断Cookie的邮箱名是否等于"HKPhotoUserEmail"
if (CommonConstants.BROWSER_COOKIE_EMAIL.equals(cookie
.getName())) {
email = cookie.getValue().trim();
}
// 判断Cookie的密码名是否等于"HKPhotoUserPassword"
if (CommonConstants.BROWSER_COOKIE_PASSWORD.equals(cookie
.getName())) {
password = cookie.getValue().trim();
}
// 判断Cookie的自动登录状态名是否等于"HKPhotoAutoLoginStatus"
if (CommonConstants.BROWSER_COOKIE_AUTO_STATUS_NAME
.equals(cookie.getName())) {
autoStatus = cookie.getValue().trim();
}
}
if (autoStatus!=null&&autoStatus.equals("1")) {
if (email != null && password != null && email.length() > 0
&& password.length() > 0) {
cookieUser = new User();
cookieUser.setEmail(email);
cookieUser.setPassword(password);
// System.out.println("email=" + cookieUser.getEmail());
// System.out.println("password="
// + cookieUser.getPassword());
IUserService userService = PicoContainer.PICO
.getComponent(IUserService.class);
cookieUser = userService.validLogin(cookieUser);
if (cookieUser != null) {
// 将该user放入到session中
request.getSession().setAttribute(
CommonConstants.SESSION_USER, cookieUser);
} else {
chain.doFilter(request, response);
}
} else {
chain.doFilter(request, response);
}
} else {
chain.doFilter(request, response);
}
} else {
chain.doFilter(request, response);
}
} else {
chain.doFilter(request, response);
}
}
}
3.web.xml配置cookie登录过滤器
Xml代码
<!-- cookie邮箱和密码登陆过滤 -->
<filter>
<filter-name>cookie-login-filter</filter-name>
<filter-class>com.hydom.filter.CookieLoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>cookie-login-filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
4.用户登录时
Java代码
public class LoginAction extends BaseAction {
private static final long serialVersionUID = 1L;
private String email = null;// 用户邮箱
private String password = null;// 用户密码
private boolean autoLoginStatus = false;
public boolean getAutoLoginStatus() {
return autoLoginStatus;
}
public void setAutoLoginStatus(boolean autoLoginStatus) {
this.autoLoginStatus = autoLoginStatus;
}
public void setEmail(String email) {
this.email = email;
}
public void setPassword(String password) {
this.password = password;
}
// 获取数据层示例
private IUserService userService = PicoContainer.PICO
.getComponent(IUserService.class);
@Override
public String execute() throws Exception {
try {
// 验证用户信息
String message = checkAndFilterUsersInfo();
;
User user = null;
if (message == null) {
user = new User();
user.setEmail(this.email);
user.setPassword(this.password);
user = userService.validLogin(user);
}
// 输出结果
StringBuilder msg = new StringBuilder();
msg.append("{");
if (user != null) {
super.getSession().setAttribute(CommonConstants.SESSION_USER,
user);
msg.append("msg:'success'").append(",");
msg.append("userName:'").append(user.getUserName()).append("'");
if (autoLoginStatus) {
// 根据选择状态判断是否将用户邮箱和密码信息保存在客户端浏览器
addCookieingUserToResponse(user);
}else{
removeCookieingUserInResponse();
}
} else {
if (message == null) {
msg.append("msg:'帳號或者密碼錯誤'");
} else {
msg.append("msg:'").append(message).append("'");
}
}
msg.append("}");
ajaxJson(msg.toString());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 将用户邮箱和密码信息添加到响应中
*
* @param cookieingUser
*/
private void addCookieingUserToResponse(User cookieingUser) {
// 设置cookie邮箱名值对
Cookie cookieEmail = new Cookie(CommonConstants.BROWSER_COOKIE_EMAIL,
cookieingUser.getEmail());
cookieEmail.setMaxAge(CommonConstants.BROWSER_COOKIE_MAX_AGE);
cookieEmail.setPath(super.getRequest().getContextPath());
super.getResponse().addCookie(cookieEmail);
// 设置cookie密码名值对
Cookie cookiePassword = new Cookie(
CommonConstants.BROWSER_COOKIE_PASSWORD, cookieingUser
.getPassword());
cookiePassword.setMaxAge(CommonConstants.BROWSER_COOKIE_MAX_AGE);
cookiePassword.setPath(super.getRequest().getContextPath());
super.getResponse().addCookie(cookiePassword);
// 设置cookie自动登录状态名值对
Cookie autoLoginStatusCookie = new Cookie(
CommonConstants.BROWSER_COOKIE_AUTO_STATUS_NAME,
"1");
autoLoginStatusCookie
.setMaxAge(CommonConstants.BROWSER_COOKIE_MAX_AGE);
autoLoginStatusCookie.setPath(super.getRequest()
.getContextPath());
super.getResponse().addCookie(autoLoginStatusCookie);
// 设置cookie登出名值对
Cookie loginOutCookie = new Cookie(
CommonConstants.BROWSER_COOKIE_LOGIN_OUT_NAME,
"0");
loginOutCookie
.setMaxAge(CommonConstants.BROWSER_COOKIE_MAX_AGE);
loginOutCookie.setPath(super.getRequest()
.getContextPath());
super.getResponse().addCookie(loginOutCookie);
}
public void removeCookieingUserInResponse(){
// 设置cookie邮箱名值对
Cookie cookieEmail = new Cookie(CommonConstants.BROWSER_COOKIE_EMAIL,
null);
cookieEmail.setMaxAge(CommonConstants.BROWSER_COOKIE_MAX_AGE);
cookieEmail.setPath(super.getRequest().getContextPath());
super.getResponse().addCookie(cookieEmail);
// 设置cookie密码名值对
Cookie cookiePassword = new Cookie(
CommonConstants.BROWSER_COOKIE_PASSWORD, null);
cookiePassword.setMaxAge(CommonConstants.BROWSER_COOKIE_MAX_AGE);
cookiePassword.setPath(super.getRequest().getContextPath());
super.getResponse().addCookie(cookiePassword);
// 设置cookie自动登录状态名值对
Cookie autoLoginStatusCookie = new Cookie(
CommonConstants.BROWSER_COOKIE_AUTO_STATUS_NAME,
"0");
autoLoginStatusCookie
.setMaxAge(CommonConstants.BROWSER_COOKIE_MAX_AGE);
autoLoginStatusCookie.setPath(super.getRequest()
.getContextPath());
super.getResponse().addCookie(autoLoginStatusCookie);
// 设置cookie登出名值对
Cookie loginOutCookie = new Cookie(
CommonConstants.BROWSER_COOKIE_LOGIN_OUT_NAME,
"0");
loginOutCookie
.setMaxAge(CommonConstants.BROWSER_COOKIE_MAX_AGE);
loginOutCookie.setPath(super.getRequest()
.getContextPath());
super.getResponse().addCookie(loginOutCookie);
}
}
5.退出
Java代码
public class LogOutAction extends BaseAction {
private static final long serialVersionUID = 1L;
// 用户登出
@Override
public String execute() throws Exception {
super.getSession().removeAttribute(CommonConstants.SESSION_USER);
// 设置cookie登出名值对
Cookie loginOutCookie = new Cookie(
CommonConstants.BROWSER_COOKIE_LOGIN_OUT_NAME,
"1");
loginOutCookie
.setMaxAge(CommonConstants.BROWSER_COOKIE_MAX_AGE);
loginOutCookie.setPath(super.getRequest()
.getContextPath());
super.getResponse().addCookie(loginOutCookie);
// 设置cookie自动登录状态名值对
Cookie autoLoginStatusCookie = new Cookie(
CommonConstants.BROWSER_COOKIE_AUTO_STATUS_NAME,
"0");
autoLoginStatusCookie
.setMaxAge(CommonConstants.BROWSER_COOKIE_MAX_AGE);
autoLoginStatusCookie.setPath(super.getRequest()
.getContextPath());
super.getResponse().addCookie(autoLoginStatusCookie);
PrintWriter out = super.getResponse().getWriter();
out.close();
return null;
}
}
6.jsp登录页面
Html代码
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<script src="<%=base%>js/common/jquery.js"></script>
<script src="<%=base%>js/common/jquery.cookie.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var email=$.cookie('<%=CommonConstants.BROWSER_COOKIE_EMAIL%>');
var password=$.cookie('<%=CommonConstants.BROWSER_COOKIE_PASSWORD%>');
var autoStatus=$.cookie('<%=CommonConstants.BROWSER_COOKIE_AUTO_STATUS_NAME%>');
var loginOut=$.cookie('<%=CommonConstants.BROWSER_COOKIE_LOGIN_OUT_NAME%>');
if(autoStatus=="0"&&loginOut=="1"){
$("#newemail").attr("value",email.replace(new RegExp('"',"gm"),""));
$("#newpassword").attr("value",password.replace(new RegExp('"',"gm"),""));
}
});
</script>
<div class="hidden" id="smallLay">
<span><a href="javascript:closedialog()" onFocus="this.blur()" > <img src="<%=base%>images/cose.gif" /></a></span>
<p class="logo"><img οnerrοr="this.src='<%=base%>images/logo.jpg'" src="<%=base%><%=logo.getSmallPath()%>" /></p>
<div class="user">
<ul>
<li><b>郵箱:</b><input type="text" id="newemail" οnblur="checkAdminEmail(this.value)" value=""/></li>
<li><b>密碼:</b><input type="password" id="newpassword" value=""/></li>
</ul>
<samp><input name="autoLoginStatus" id="autoLoginStatus" checked="checked" type="checkbox" value="" class="check"/><d>下次自動登陸</d> <a href="javascript:startRegister()" style="color:red;text-decoration: underline;"">忘記密碼</a></samp>
<p><input type="button" class="land" οnclick="gologin()" value="登 录"/></p>
<samp><b>使用合作網站帳號登陸:</b><img src="<%=base%>images/f.gif" οnclick="tofacelogin()"/><u></u><img src="<%=base%>images/sina.gif" /></samp>
</div>
</div>
作者“成功需要沉寂时间来练功”
登陆模块(三)--使用cookie自动登录
<!--------index.asp---------->
<%
if request.Cookies("User")("Name")="" then
%>
<form method=post name=login action=login.asp>
<div align=center>
<table cellspacing=5 cellpadding=5>
<tr>
<td colspan=2>您还没有登录!</td>
</tr>
<tr>
<td width=60 align=right>用户名: </td><td align=left><input name=Name class=inp></td>
</tr>
<tr>
<td width=60 align=right>密 码: </td><td align=left><input name=Pwd class=inp type=password></td>
</tr>
<tr>
<td width=60 align=right>保存期限: </td><td align=left><select name=Cookies_Time>
<option value=1>1
<option value=7>1周
</select></td>
</tr>
<tr>
<td colspan=2><input type=submit value=提交></td>
</tr>
</form>
<%
else
%>
欢迎您,</span><%=request.cookies("User")("Name")%>。
<%
end if
%>
<!-------------login.asp----------->
<%
Response.Cookies("User")("Name")= request("Name")
Response.Cookies("User")("Pwd")= request("Pwd")
Cookies_Time=request.form("Cookies_Time")
if Cookies_Time="" then Cookies_Time=1
if Cookies_Time<>"0" then
Cookies_Time=dateadd("d",Cookies_Time,date())
Response.Cookies("User").expires=Cookies_Time
response.redirect "index.asp"
end if
%>
创建了cookie字典:User,修改“User”cookie的保存期限,则其Name,Pwd两项的保存期限都修改了。
由于是第一次登录,所以没有cookie保存在C:\Documents and Settings\Administrator\C
ookies文件夹和C:\Documents and Settings\Administrator\Local Settings\Temporary Internet Files文件夹,在填写用户名和密码以及保存cookies的时间期限后,点击"提交"按钮,在Temporary Internet Files(点击IE的"工具" ->" Internet 选项"的"Internet 临时文件"这一栏目的"设置" -> "查看"按钮即可打开该文件夹。)文件夹里即可产生一个cookie文件,如果按"详细资料"查看的话,很清楚的可以看到在"截止期"的时间就是cookie过期时间。也可以保存cookie过期时间为几小时,将上面代码中的dateadd("d",Cookies_Time,date())改成dateadd("h",Cookies_Time,now())即可。
写cookie: response.cookies("xx")=值
读cookie: request.cookies("xx")
也可以像上面中的代码一样创建cookie字典。
DateAdd函数
计算在给定日期上加一个时间间隔后的新日期。
#include <Date.au3>
_DateAdd ( $sType, $iValToAdd, $sDate )
参数
$sType D = 增加指定数量的天数到给定的日期。
M = 增加指定数量的月数到给定的日期。
Y = 增加指定数量的年数到给定的日期。
w = 增加指定数量的周数到给定的日期。
h = 增加指定数量的时数到给定的日期。
n = 增加指定数量的分数到给定的日期。
s = 增加指定数量的秒数到给定的日期。
$iValToAdd 要增加的(时间单位)数量。
$sDate 格式为 "YYYY/MM/DD[ HH:MM:SS]" 的输入日期。
登陆的时候一旦选择了[自动登录]的选项,则需要在登陆成功后,附加下面的代码
应为一般网站都提供保存用户名的功能,所以我把这个写到了外面。只有密码是单独处理的。
其中的host就是你的域名。
第一步,编写login.jsp文件,内容如下:
本部分设定了隐藏,您已回复过了,以下是隐藏的内容
String host = request.getServerName();
Cookie cookie = new Cookie("SESSION_LOGIN_USERNAME", username); // 保存用户名到Cookie
cookie.setPath("/");
cookie.setDomain(host);
cookie.setMaxAge(99999999);
response.addCookie(cookie);
if (ParamUtils.getBooleanParameter(request, "savePassword")) {
// 保存密码到Cookie,注意需要加密一下
cookie = new Cookie("SESSION_LOGIN_PASSWORD", MD5.encode(u.getPassword()));
cookie.setPath("/");
cookie.setDomain(host);
cookie.setMaxAge(99999999);
response.addCookie(cookie);
}
这样,Cookie就生成了
第二步,在用户访问网站的时候,如果检测到没有登陆,则进行下面的判断,
例如编写一个index.jsp,内容如下:
String usernameCookie = null;
String passwordCookie = null;
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if ("SESSION_LOGIN_USERNAME".equals(cookie.getName())) {
usernameCookie = cookie.getValue(); // 得到cookie的用户名
}
if ("SESSION_LOGIN_PASSWORD".equals(cookie.getName())) {
passwordCookie = cookie.getValue(); // 得到cookie的密码
}
}
if (usernameCookie != null && passwordCookie != null) { // 如果存在
if(Login.checkLogin(usernameCookie ,passwordCookie)){
// 登陆成功的处理
}else{
// 登陆不成功的处理
}
}
}
这部份代码可以写到action或servlet中。最后一个注意事项,应该在退出登录里面清除cookie,以免他无法换账号登陆了!
logout.jsp内容如下:
cookie = new Cookie("SESSION_LOGIN_PASSWORD", "");
cookie.setPath("/");
cookie.setMaxAge(99999999);
cookie.setDomain(host);
response.addCookie(cookie);
注意事项:
一旦自动登录失败,则取消其自动登录的可能性,防止暴力破解! 所以通常会在对应的实体中定义一个属性来标示是否自动登录,也就是说:这个标志只有下次正常输入验证码的登陆才会被清除!!
jsp使用cookie实现自动登录
一、什么是用户自动登录?
对于我们的网站向已注册用户提供某些专门的服务,比如网上购物、在线下载、收费浏览等等,就会要求用户在使用这些服务之前进入登录页面,输入用户名和密码,并进行验证。
如果用户经常访问我们的网站,假如每天都访问一次,或者好几次,那么用户每次都重复这些登录操作就会感到相当厌烦。通过一些简单的技术手段,我们可以让网站“记住”那些在曾经登录过的用户。当该用户下次再来访问的时候,网站可以识别该用户,并为其自动完成登录过程。
二、基本思路
作为网站的编写者,我们无从知道坐在电脑前的那个人是谁。我们能够知道的是,访问网站的是哪一台电脑——这一点可以通过Cookie实现。因此,对用户的识别实际上就是对客户端电脑的识别。
简单的说,当用户第一次登录网站的时候,网站向客户端发送一个包含有用户名的Cookie。当用户在之后的某个时候再次访问,浏览器就会向网站服务器回送这个Cookie,于是,我们可以从这个Cookie中读取到用户名,然后调用登录的方法,从而实现自动为用户登录。
三、防止欺骗
Cookie只是一个普通的文本文件,那里面包含的字符串可以直接用记事本打开并进行编辑。因此任何人在任何电脑上都可以伪造一个包含有他人用户名 的 Cookie,
从而实现对他人身份的冒用。要解决这个问题,就要在Cookie中附加一项信息,这个信息需要具有以下特性:
1、和该用户一一对应;2、伪 造难度大。这些内容和用户名一起,以Cookie的形式发送给用户的浏览器。
并且,服务器必须能够记住这项内容,以便用户再次访问的时候进行核对。
理论上,可以使用该用户的密码。密码具备了前述的两个特点。但是因为Cookie本身未经加密,保存于其中的密码(应该加密)可以被任何人看到,因此这个方法极不安全。
另一种可以加以利用的信息是用户访问时的Session id。因为Session id是一个由系统随机产生的、无规律的、长度较长的字符串,因此它很难被伪造。
要把它和用户对应起来,我们需要在数据库中添加一个表,这个表至少有两个字 段,一个是用户名,一个是Session id。
当用户首次登录的时候,我们把当前的Session id和用户名分别用Cookie发送给用户,同时,把这两项作为一条记录插入数据库。
这样,当用户再次访问的时候,服务器就可以读取客户端发来的这两个 Cookie,并且用它们的值和数据库中的记录比对。
如果在数据库中找到了相应记录,就说明这台电脑的确是该用户上次登录时使用的电脑,进而可以为该用户自动登录。
四、实现
1、在登录页面中添加一个复选框,让用户选择是否愿意在一定时间内实现自动登陆,例如两周。
代码:
<input type="checkbox" name="autologin">两周内自动登录
2、在负责处理登录过程的Servlet中,判断用户是否选择了该复选框。如果是,则执行这两个操作:向用户发送两个Cookie,以及向数据库写入一条相应的记录。
代码:
Cookie ckUsername, ckSessionid;
if (autologin.equals("on")) {
// 如果用户选择了“两周内自动登录”,则向用户发送两个cookie。
// 一个cookie记录用户名,另一个记录唯一的验证码,
// 并将此验证码写入数据库,以备用户返回时查询。(防止伪造cookie)
ckUsername = new Cookie("autoLoginUser", user.getUsername()); // user是代表用户的bean
ckUsername.setMaxAge(60 * 60 * 24 * 14); //设置Cookie有效期为14天
res.addCookie(ckUsername);
sessionid = session.getId(); // 取得当前的session id
ckSessionid = new Cookie("sessionid", sessionid);
ckSessionid.setMaxAge(60 * 60 * 24 * 14);
res.addCookie(ckSessionid);
// 在数据库中插入相应记录
userSessionDAO.insertUserSession(user, sessionid);
}
3、实现自动登录。因为用户下次访问的时候,可能直接访问网站的任何页面(例如通过收藏夹),而不一定是首页或者登录页面,
所以我们需要用Filter拦截到达该网站的所有请求,并执行自动登录。
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpSession session = request.getSession(true);
String username;
String sessionid; // 此sessionid是上次用户登录时保存于用户端的识别码,用于用户后续访问的自动登录。不是本次访问的session id。
Cookie[] cookies;
CookieManager cm = new CookieManager(); // CookieManager是一个自定义的类,用于从Cookie数组中查找并返回指定名称的Cookie值。
boolean isAutoLogin;
// 如果session中没有user对象,则创建一个。
User user = (User) session.getAttribute("user");
if (user == null) {
user = new User(); // 此时user中的username属性为"",表示用户未登录。
}
// 如果user对象的username为"",表示用户未登录。则执行自动登录过程。
// 否则不自动登录。
if (user.getUsername().equals("")) {
// 检查用户浏览器是否发送了上次登录的用户名和sessionid,
// 如果是,则为用户自动登陆。
cookies = request.getCookies();
username = cm.getCookieValue(cookies, "autoLoginUser");
sessionid = cm.getCookieValue(cookies, "sessionid");
isAutoLogin = userSessionDAO.getAutoLoginState(username, sessionid); // 如果在数据库中找到了相应记录,则说明可以自动登录。
if (isAutoLogin) {
user.setUsername(username);
user.setNickname(DBUtil.getNickName(username));
session.setAttribute("user", user); // 将user bean添加到session中。
}
}
chain.doFilter(req, resp);
}
4、注销。只有当用户在上次访问时,未经注销就离开网站,我们才能在该用户下次访问时执行自动登录。如果用户显式的执行了注销操作,那就表示该用户 不希望我们记住他。我们需要在执行注销操作的Servlet中,从数据库中删除相应记录。这样,下次用户访问的时候就不会执行自动登录了。
五、改进
用户可能为了方便,自行修改Cookie中的有效期,从而达到长期自动登录的目的。对某些存有敏感信息的网站来说,这样做并不安全。当用户长时间没有使用他的电脑,或者将电脑遗弃、转让了,而保存于其中的Cookie仍然是有效的,这就为用户和网站带来潜在的风险。
要解决这个问题,我们可以在数据库中增加一个字段,用以记录自动登录的过期日。这样,是否执行自动登录就不再以客户端的Cookie有效期为准,而 是以服务器端数据库中的信息为准。当我们想要调整用户自动登录的有效期的时候,只需要修改数据库中相应的日期字段即可,因而这一过程变得更加安全。
1.用到的常量
Java代码
package com.hydom.util;
public final class CommonConstants {
// 系统 session 用户
public final static String SESSION_USER = "session_user";
/** 保存在浏览器中cookie的邮箱名称名 */
public final static String BROWSER_COOKIE_EMAIL = "HKPhotoUserEmail";
/** 保存在浏览器中cookie的邮箱密码名 */
public final static String BROWSER_COOKIE_PASSWORD = "HKPhotoUserPassword";
/** 保存在浏览器中cookie的最大时间15天 */
public final static int BROWSER_COOKIE_MAX_AGE = 15*24*60*60;
/** 保存在浏览器中cookie的自动登录状态名 */
public final static String BROWSER_COOKIE_AUTO_STATUS_NAME = "HKPhotoAutoLoginStatus";
/** 保存在浏览器中cookie的退出登录名 */
public final static String BROWSER_COOKIE_LOGIN_OUT_NAME = "HKPhotoLoginOut";
}
2.过滤器
Java代码
package com.hydom.filter;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.hydom.entity.User;
import com.hydom.service.IUserService;
import com.hydom.util.CommonConstants;
import com.hydom.util.pico.PicoContainer;
/**
*功能:首先检测session中是否有user,如果没有再检测cookie中是否有对应的邮箱和密码<BR>
* 如果有那么就查出该user放进session中<BR>
* 如果都没有那么就doFilter()<BR>
*
* @author ocaicai@yeah.net<BR>
* @date 2011-9-22<BR>
* @version 1.0 <BR>
*
*/
public class CookieLoginFilter extends BaseFilter {
// 获取数据层示例
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
Object object = request.getSession().getAttribute(
CommonConstants.SESSION_USER);
User cookieUser = null;
String email = null;
String password = null;
String autoStatus = null;
if (object == null) {
Cookie[] cookies = request.getCookies();
if (cookies != null && cookies.length > 0) {
// System.out.println("cookies.length=" + cookies.length);
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
// 判断Cookie的邮箱名是否等于"HKPhotoUserEmail"
if (CommonConstants.BROWSER_COOKIE_EMAIL.equals(cookie
.getName())) {
email = cookie.getValue().trim();
}
// 判断Cookie的密码名是否等于"HKPhotoUserPassword"
if (CommonConstants.BROWSER_COOKIE_PASSWORD.equals(cookie
.getName())) {
password = cookie.getValue().trim();
}
// 判断Cookie的自动登录状态名是否等于"HKPhotoAutoLoginStatus"
if (CommonConstants.BROWSER_COOKIE_AUTO_STATUS_NAME
.equals(cookie.getName())) {
autoStatus = cookie.getValue().trim();
}
}
if (autoStatus!=null&&autoStatus.equals("1")) {
if (email != null && password != null && email.length() > 0
&& password.length() > 0) {
cookieUser = new User();
cookieUser.setEmail(email);
cookieUser.setPassword(password);
// System.out.println("email=" + cookieUser.getEmail());
// System.out.println("password="
// + cookieUser.getPassword());
IUserService userService = PicoContainer.PICO
.getComponent(IUserService.class);
cookieUser = userService.validLogin(cookieUser);
if (cookieUser != null) {
// 将该user放入到session中
request.getSession().setAttribute(
CommonConstants.SESSION_USER, cookieUser);
} else {
chain.doFilter(request, response);
}
} else {
chain.doFilter(request, response);
}
} else {
chain.doFilter(request, response);
}
} else {
chain.doFilter(request, response);
}
} else {
chain.doFilter(request, response);
}
}
}
3.web.xml配置cookie登录过滤器
Xml代码
<!-- cookie邮箱和密码登陆过滤 -->
<filter>
<filter-name>cookie-login-filter</filter-name>
<filter-class>com.hydom.filter.CookieLoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>cookie-login-filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
4.用户登录时
Java代码
public class LoginAction extends BaseAction {
private static final long serialVersionUID = 1L;
private String email = null;// 用户邮箱
private String password = null;// 用户密码
private boolean autoLoginStatus = false;
public boolean getAutoLoginStatus() {
return autoLoginStatus;
}
public void setAutoLoginStatus(boolean autoLoginStatus) {
this.autoLoginStatus = autoLoginStatus;
}
public void setEmail(String email) {
this.email = email;
}
public void setPassword(String password) {
this.password = password;
}
// 获取数据层示例
private IUserService userService = PicoContainer.PICO
.getComponent(IUserService.class);
@Override
public String execute() throws Exception {
try {
// 验证用户信息
String message = checkAndFilterUsersInfo();
;
User user = null;
if (message == null) {
user = new User();
user.setEmail(this.email);
user.setPassword(this.password);
user = userService.validLogin(user);
}
// 输出结果
StringBuilder msg = new StringBuilder();
msg.append("{");
if (user != null) {
super.getSession().setAttribute(CommonConstants.SESSION_USER,
user);
msg.append("msg:'success'").append(",");
msg.append("userName:'").append(user.getUserName()).append("'");
if (autoLoginStatus) {
// 根据选择状态判断是否将用户邮箱和密码信息保存在客户端浏览器
addCookieingUserToResponse(user);
}else{
removeCookieingUserInResponse();
}
} else {
if (message == null) {
msg.append("msg:'帳號或者密碼錯誤'");
} else {
msg.append("msg:'").append(message).append("'");
}
}
msg.append("}");
ajaxJson(msg.toString());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 将用户邮箱和密码信息添加到响应中
*
* @param cookieingUser
*/
private void addCookieingUserToResponse(User cookieingUser) {
// 设置cookie邮箱名值对
Cookie cookieEmail = new Cookie(CommonConstants.BROWSER_COOKIE_EMAIL,
cookieingUser.getEmail());
cookieEmail.setMaxAge(CommonConstants.BROWSER_COOKIE_MAX_AGE);
cookieEmail.setPath(super.getRequest().getContextPath());
super.getResponse().addCookie(cookieEmail);
// 设置cookie密码名值对
Cookie cookiePassword = new Cookie(
CommonConstants.BROWSER_COOKIE_PASSWORD, cookieingUser
.getPassword());
cookiePassword.setMaxAge(CommonConstants.BROWSER_COOKIE_MAX_AGE);
cookiePassword.setPath(super.getRequest().getContextPath());
super.getResponse().addCookie(cookiePassword);
// 设置cookie自动登录状态名值对
Cookie autoLoginStatusCookie = new Cookie(
CommonConstants.BROWSER_COOKIE_AUTO_STATUS_NAME,
"1");
autoLoginStatusCookie
.setMaxAge(CommonConstants.BROWSER_COOKIE_MAX_AGE);
autoLoginStatusCookie.setPath(super.getRequest()
.getContextPath());
super.getResponse().addCookie(autoLoginStatusCookie);
// 设置cookie登出名值对
Cookie loginOutCookie = new Cookie(
CommonConstants.BROWSER_COOKIE_LOGIN_OUT_NAME,
"0");
loginOutCookie
.setMaxAge(CommonConstants.BROWSER_COOKIE_MAX_AGE);
loginOutCookie.setPath(super.getRequest()
.getContextPath());
super.getResponse().addCookie(loginOutCookie);
}
public void removeCookieingUserInResponse(){
// 设置cookie邮箱名值对
Cookie cookieEmail = new Cookie(CommonConstants.BROWSER_COOKIE_EMAIL,
null);
cookieEmail.setMaxAge(CommonConstants.BROWSER_COOKIE_MAX_AGE);
cookieEmail.setPath(super.getRequest().getContextPath());
super.getResponse().addCookie(cookieEmail);
// 设置cookie密码名值对
Cookie cookiePassword = new Cookie(
CommonConstants.BROWSER_COOKIE_PASSWORD, null);
cookiePassword.setMaxAge(CommonConstants.BROWSER_COOKIE_MAX_AGE);
cookiePassword.setPath(super.getRequest().getContextPath());
super.getResponse().addCookie(cookiePassword);
// 设置cookie自动登录状态名值对
Cookie autoLoginStatusCookie = new Cookie(
CommonConstants.BROWSER_COOKIE_AUTO_STATUS_NAME,
"0");
autoLoginStatusCookie
.setMaxAge(CommonConstants.BROWSER_COOKIE_MAX_AGE);
autoLoginStatusCookie.setPath(super.getRequest()
.getContextPath());
super.getResponse().addCookie(autoLoginStatusCookie);
// 设置cookie登出名值对
Cookie loginOutCookie = new Cookie(
CommonConstants.BROWSER_COOKIE_LOGIN_OUT_NAME,
"0");
loginOutCookie
.setMaxAge(CommonConstants.BROWSER_COOKIE_MAX_AGE);
loginOutCookie.setPath(super.getRequest()
.getContextPath());
super.getResponse().addCookie(loginOutCookie);
}
}
5.退出
Java代码
public class LogOutAction extends BaseAction {
private static final long serialVersionUID = 1L;
// 用户登出
@Override
public String execute() throws Exception {
super.getSession().removeAttribute(CommonConstants.SESSION_USER);
// 设置cookie登出名值对
Cookie loginOutCookie = new Cookie(
CommonConstants.BROWSER_COOKIE_LOGIN_OUT_NAME,
"1");
loginOutCookie
.setMaxAge(CommonConstants.BROWSER_COOKIE_MAX_AGE);
loginOutCookie.setPath(super.getRequest()
.getContextPath());
super.getResponse().addCookie(loginOutCookie);
// 设置cookie自动登录状态名值对
Cookie autoLoginStatusCookie = new Cookie(
CommonConstants.BROWSER_COOKIE_AUTO_STATUS_NAME,
"0");
autoLoginStatusCookie
.setMaxAge(CommonConstants.BROWSER_COOKIE_MAX_AGE);
autoLoginStatusCookie.setPath(super.getRequest()
.getContextPath());
super.getResponse().addCookie(autoLoginStatusCookie);
PrintWriter out = super.getResponse().getWriter();
out.close();
return null;
}
}
6.jsp登录页面
Html代码
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<script src="<%=base%>js/common/jquery.js"></script>
<script src="<%=base%>js/common/jquery.cookie.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var email=$.cookie('<%=CommonConstants.BROWSER_COOKIE_EMAIL%>');
var password=$.cookie('<%=CommonConstants.BROWSER_COOKIE_PASSWORD%>');
var autoStatus=$.cookie('<%=CommonConstants.BROWSER_COOKIE_AUTO_STATUS_NAME%>');
var loginOut=$.cookie('<%=CommonConstants.BROWSER_COOKIE_LOGIN_OUT_NAME%>');
if(autoStatus=="0"&&loginOut=="1"){
$("#newemail").attr("value",email.replace(new RegExp('"',"gm"),""));
$("#newpassword").attr("value",password.replace(new RegExp('"',"gm"),""));
}
});
</script>
<div class="hidden" id="smallLay">
<span><a href="javascript:closedialog()" onFocus="this.blur()" > <img src="<%=base%>images/cose.gif" /></a></span>
<p class="logo"><img οnerrοr="this.src='<%=base%>images/logo.jpg'" src="<%=base%><%=logo.getSmallPath()%>" /></p>
<div class="user">
<ul>
<li><b>郵箱:</b><input type="text" id="newemail" οnblur="checkAdminEmail(this.value)" value=""/></li>
<li><b>密碼:</b><input type="password" id="newpassword" value=""/></li>
</ul>
<samp><input name="autoLoginStatus" id="autoLoginStatus" checked="checked" type="checkbox" value="" class="check"/><d>下次自動登陸</d> <a href="javascript:startRegister()" style="color:red;text-decoration: underline;"">忘記密碼</a></samp>
<p><input type="button" class="land" οnclick="gologin()" value="登 录"/></p>
<samp><b>使用合作網站帳號登陸:</b><img src="<%=base%>images/f.gif" οnclick="tofacelogin()"/><u></u><img src="<%=base%>images/sina.gif" /></samp>
</div>
</div>
作者“成功需要沉寂时间来练功”
登陆模块(三)--使用cookie自动登录
<!--------index.asp---------->
<%
if request.Cookies("User")("Name")="" then
%>
<form method=post name=login action=login.asp>
<div align=center>
<table cellspacing=5 cellpadding=5>
<tr>
<td colspan=2>您还没有登录!</td>
</tr>
<tr>
<td width=60 align=right>用户名: </td><td align=left><input name=Name class=inp></td>
</tr>
<tr>
<td width=60 align=right>密 码: </td><td align=left><input name=Pwd class=inp type=password></td>
</tr>
<tr>
<td width=60 align=right>保存期限: </td><td align=left><select name=Cookies_Time>
<option value=1>1
<option value=7>1周
</select></td>
</tr>
<tr>
<td colspan=2><input type=submit value=提交></td>
</tr>
</form>
<%
else
%>
欢迎您,</span><%=request.cookies("User")("Name")%>。
<%
end if
%>
<!-------------login.asp----------->
<%
Response.Cookies("User")("Name")= request("Name")
Response.Cookies("User")("Pwd")= request("Pwd")
Cookies_Time=request.form("Cookies_Time")
if Cookies_Time="" then Cookies_Time=1
if Cookies_Time<>"0" then
Cookies_Time=dateadd("d",Cookies_Time,date())
Response.Cookies("User").expires=Cookies_Time
response.redirect "index.asp"
end if
%>
创建了cookie字典:User,修改“User”cookie的保存期限,则其Name,Pwd两项的保存期限都修改了。
由于是第一次登录,所以没有cookie保存在C:\Documents and Settings\Administrator\C
ookies文件夹和C:\Documents and Settings\Administrator\Local Settings\Temporary Internet Files文件夹,在填写用户名和密码以及保存cookies的时间期限后,点击"提交"按钮,在Temporary Internet Files(点击IE的"工具" ->" Internet 选项"的"Internet 临时文件"这一栏目的"设置" -> "查看"按钮即可打开该文件夹。)文件夹里即可产生一个cookie文件,如果按"详细资料"查看的话,很清楚的可以看到在"截止期"的时间就是cookie过期时间。也可以保存cookie过期时间为几小时,将上面代码中的dateadd("d",Cookies_Time,date())改成dateadd("h",Cookies_Time,now())即可。
写cookie: response.cookies("xx")=值
读cookie: request.cookies("xx")
也可以像上面中的代码一样创建cookie字典。
DateAdd函数
计算在给定日期上加一个时间间隔后的新日期。
#include <Date.au3>
_DateAdd ( $sType, $iValToAdd, $sDate )
参数
$sType D = 增加指定数量的天数到给定的日期。
M = 增加指定数量的月数到给定的日期。
Y = 增加指定数量的年数到给定的日期。
w = 增加指定数量的周数到给定的日期。
h = 增加指定数量的时数到给定的日期。
n = 增加指定数量的分数到给定的日期。
s = 增加指定数量的秒数到给定的日期。
$iValToAdd 要增加的(时间单位)数量。
$sDate 格式为 "YYYY/MM/DD[ HH:MM:SS]" 的输入日期。