案例三:实现用户的自动登录

实现用户自动登录的过滤器

当用户登录的时候勾选了自动登录选项,那么首次登录会把用户的账户密码保存到Cookie,当用户退出登录后重新访问某些页面,符合条件的将会先被filter拦截实现自动登录的功能,即使用户关闭浏览器了,只要Cookie没有过期,再次打开页面如果符合条件也是可以完成自动登录的.

需要注意的是,如果用户点击了退出登录后返回的页面(一般都是通过重定向返回的),如果返回的页面仍然被自动登录的filter所匹配,那么就会造成退出不了的死循环,因为退出成功后重定向也会被再次拦截,拦截又被自动登录了.解决办法就是在退出登录的时候通过session保存一个标记,然后被filter拦截后再取出这个标记判断,如果是来自退出登录页的则不做自动登录操作.

filter代码如下:

package blog.csdn.net.web.filter;

import java.io.IOException;
import java.net.URLDecoder;
import java.sql.SQLException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
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 javax.servlet.http.HttpSession;

import blog.csdn.net.web.domain.User;
import blog.csdn.net.web.service.UserService;
import blog.csdn.net.web.util.CookieUtils;
import blog.csdn.net.web.util.StringUtils;

/**
 * 处理自动登录的Filter,当用户登录的时候勾选了自动登录,用户退出登录后,下次访问,会判断cookie中保存的用户名密码完成自动登录
 * 
 * @author mChenys
 *
 */
public class AutoLoginFilter implements Filter {

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {

	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// 强转
		HttpServletRequest httpServletRequest = (HttpServletRequest) request;
		HttpServletResponse httpServletResponse = (HttpServletResponse) response;
		HttpSession session = httpServletRequest.getSession();
		
		
		// 获取session域中保存的user
		User user =null;
		if(null !=session.getAttribute("user")&& 
				(user= (User) session.getAttribute("user")) ==null) {
			
			// 获取为null表示用户已经退出了登录
			// 避免刚刚退出登录的时候重定向到首页又被拦截了,所以从header中获取标记判断
			
			boolean isFromLogout = false;
			if(null !=session.getAttribute("isLogout")) {
				isFromLogout = (boolean) session.getAttribute("isLogout");
			}
			
			if (!isFromLogout) {
				// 判断用户访问的页面是否需要自动登录,这里除了访问登录和退出的请求都需要完成自动登录
				// 否则访问登录的永远都是上次勾选自动登录的账户,访问退出登录永远都退不了
				String path = httpServletRequest.getRequestURI();
				if (!path.contains("/login") && !path.contains("/logout")) {
					// 获取cookie中保存的账号和密码
					Cookie loginCookie = CookieUtils.getCookieByName("autoLogin", httpServletRequest.getCookies());
					if (null != loginCookie) {
						// 切割用户名和密码
						String username = loginCookie.getValue().split("#")[0];
						String password = loginCookie.getValue().split("#")[1];
						// 用户名需要解码
						username = URLDecoder.decode(username, "utf-8");
						// 尝试登录
						try {
							user = new UserService().login(username, password);
							System.out.println(username + ":自动登录成功...");
						} catch (SQLException e) {
							e.printStackTrace();
						}
						if (null != user) {
							// 自动登录成功,保存到session域中,避免重复自动登录
							session.setAttribute("user", user);

						}
					}
				}
			}

		}
		// 重置下标记
		session.setAttribute("isLogout", false);
		// 发现
		chain.doFilter(httpServletRequest, response);

	}

	@Override
	public void destroy() {

	}

}

注册filter

<!--  自动登录拦截-->
<filter>
    <filter-name>AutoLoginFilter</filter-name>
    <filter-class>blog.csdn.net.web.filter.AutoLoginFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>AutoLoginFilter</filter-name>
    <url-pattern>/home</url-pattern>
    <!-- 
	REQUEST(默认类型):只拦截从浏览器发送来的请求,包括了重定向,因为重定向相当于让浏览器重新发送一个    新的请求
     -->
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

登录的Servlet代码如下:

package blog.csdn.net.web.servlet;

import java.io.IOException;
import java.net.URLEncoder;
import java.sql.SQLException;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import blog.csdn.net.web.domain.User;
import blog.csdn.net.web.service.UserService;
import blog.csdn.net.web.util.CookieUtils;
import blog.csdn.net.web.util.StringUtils;

/**
 * 用户登录
 */
public class LoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");

		String username = request.getParameter("username");
		String password = request.getParameter("password");
		String saveName = request.getParameter("saveName");
		String autoLogin = request.getParameter("autoLogin");

		if (StringUtils.isEmpty(username)) {
			request.setAttribute("usermsg", "用户名为空");
			request.getRequestDispatcher("/login.jsp").forward(request, response);
			return;
		}
		if (StringUtils.isEmpty(password)) {
			request.setAttribute("pwdmsg", "密码为空");
			request.getRequestDispatcher("/login.jsp").forward(request, response);
			return;
		}

		User user = null;
		try {
			user = new UserService().login(username, password);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		if (null == user) {
			// 转发
			request.setAttribute("errormsg", "用户不存在或用户名密码错误");
			request.getRequestDispatcher("/login.jsp").forward(request, response);
		} else {
			// 登录成功,将用户保存到session中
			HttpSession session = request.getSession();
			session.setAttribute("user", user);
			
			// 记住用户名密码
			if ("on".equals(saveName)) {
				// 为了可以让cookie保存中文,账号名需要编码下,页面再解码使用
				Cookie saveNameCookie = new Cookie("saveName", URLEncoder.encode(username, "utf-8"));
				saveNameCookie.setMaxAge(3600);
				saveNameCookie.setPath(request.getContextPath() + "/");
				response.addCookie(saveNameCookie);
			} else {  
				// 清除用户名
				Cookie saveNameCookie = CookieUtils.getCookieByName("saveName", request.getCookies());
				if (null != saveNameCookie) {
					saveNameCookie.setPath(request.getContextPath() + "/");
					saveNameCookie.setMaxAge(0);
					response.addCookie(saveNameCookie);
				}
			}

			// 自动登录
			if ("on".equals(autoLogin)) {
				Cookie autoLoginCookie = new Cookie("autoLogin", URLEncoder.encode(username, "utf-8") + "#" + password);
				autoLoginCookie.setMaxAge(3600);
				autoLoginCookie.setPath(request.getContextPath() + "/");
				response.addCookie(autoLoginCookie);
			} else {
				// 清除自动登录
				Cookie autoLoginCookie = CookieUtils.getCookieByName("autoLogin", request.getCookies());
				if (null != autoLoginCookie) {
					autoLoginCookie.setPath(request.getContextPath() + "/");
					autoLoginCookie.setMaxAge(0);
					response.addCookie(autoLoginCookie);
				}
			}

			if (user.getUsername().equals("admin")) {
				response.sendRedirect(request.getContextPath() + "/productList");
			} else {
				response.sendRedirect(request.getContextPath() + "/home");
			}

		}
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}

}

 login.jsp

<%@page import="blog.csdn.net.web.util.CookieUtils"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录页</title>
<style type="text/css">
.body {
	margin: 20% auto 0;
	width: 70%;
	text-align: center;
}

.login {
	width: 400px;
	background-color: #cccccc;
	padding: 30px 10px;
	margin: auto;
}

h2 {
	margin-bottom: 30px;
}

form {
	padding: auto;
}

.msg {
	color: red
}

table td {
	padding: 10px 0px;
}
</style>

<script type="text/javascript">
	function savename(){
		var checkBox = document.getElementById("saveName");
		checkBox.checked=!checkBox.checked;
	}
	function autologin(){
		var checkBox = document.getElementById("autoLogin");
		checkBox.checked=!checkBox.checked;
	}
	//显示已经记住的用户名
	 onload = function(){
		var nameObj = document.getElementsByName("username")[0];
		if(${not empty cookie.saveName}){
			var username = decodeURI("${cookie.saveName.value}");
			nameObj.value = username;
		}
	}
	
</script>
</head>
<body>
	<div class="body">
		<div class="login">
			<h2>用户登录</h2>
			<form action="${pageContext.request.contextPath }/login"
				method="post" autocomplete="off">

				<table align="center">
					<tr align="left">
						<td>用户名:</td>
						<td>
							<input type="text" name="username" maxlength="6" autocomplete="new-password"/> 
							<span class="msg">${usermsg}</span>
						</td>
					</tr>
					<tr align="left">
						<td>密码:</td>
						<td>
							<input type="password" name="password" maxlength="6" autocomplete="new-password">
							<span class="msg">${pwdmsg}</span>
						</td>
					</tr>
					<tr align="left">
						<td>
							<c:if test="${empty cookie.saveName}">
								<input id="saveName" type="checkbox" name="saveName" />
								<span onclick="savename()">记住用户名</span>
							</c:if> 
							<c:if test="${not empty cookie.saveName}">
								<input id="saveName" type="checkbox" name="saveName"
									checked="checked" />
								<span onclick="savename()">记住用户名</span>
							</c:if>
						</td>
						<td>
							<c:if test="${empty cookie.autoLogin}">
								<input id="autoLogin" type="checkbox" name="autoLogin" />
								<span onclick="autologin()">自动登录</span>
							</c:if>
							 <c:if test="${not empty cookie.autoLogin}">
								<input id="autoLogin" type="checkbox" name="autoLogin"
									checked="checked" />
								<span onclick="autologin()">自动登录</span>
							</c:if>
						</td>
					</tr>
					<tr>
						<td colspan="2" align="right"><input type="submit" value="登录" /></td>
					</tr>
				</table>
			</form>
			<span class="msg">${errormsg}</span>
		</div>

	</div>
</body>

</html>

登录页效果图:

猜你喜欢

转载自blog.csdn.net/mchenys/article/details/81215203