功能:第一次登录时,勾选自动登录,关闭浏览器,再次打开,系统会自动进行用户已经登陆状态
实现用户自动登录的过滤器:
- 在用户登录成功后,以cookis形式发送用户名、密码给客户端
- 编写一个过滤器,filter方法中检查cookie中是否带有用户名、密码信息,如果存在则调用业务层登陆方法,登陆成功后则向session(关于session介绍见http://blog.csdn.net/megustas_jjc/article/details/53443012)中存入user对象(即用户登陆标记),以实现程序完成自动登陆。
数据库保存用户信息
(1)创建数据表
create table user{id int primary key auto_increment,username varchar(40),password varchar(40),role varchar(40)
}
(2)插入数据
insert into user values(null,'aaa','111','admin');
insert into user values(null,'bbb','111','user');
insert into user values(null,'ccc','111','user');
登录界面
<body>
<h1>登录表单</h1>
<h3 style="color:red;">${msg }</h3>
<form action="/megustas/login" method="post"><table><tr><td>用户名</td><td><input type="text" name="username" /></td></tr><tr><td>密码</td><td><input type="password" name="password" /></td></tr><tr><td><input type="checkbox" name="autologin" value="true" /></td><td>自动登录</td> </tr><tr><td colspan="2"><input type="submit" value="登录" /></td></tr></table>
</form>
</body>
连接数据库完成登录
(为了简洁,此处不使用DAO模式,直接将数据库的相关操作写入servlet)
定义一个JavaBean存储用户数据
public class User {private int id;private String username;private String password;private String role;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getRole() {return role;}public void setRole(String role) {this.role = role;}}
连接数据库进行登录
public class LoginServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 获得用户名和密码String username = request.getParameter("username");String password = request.getParameter("password");// MD5 加密password = DigestUtils.md5(password);// 查询数据库String sql = "select * from user where username = ? and password= ?";Object[] args = { username, password };QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());try {User user = queryRunner.query(sql,new BeanHandler<User>(User.class), args);if (user == null) {// 查询用户不存在,登陆失败request.setAttribute("msg", "用户名或者密码错误");//转发可以传数据,重定向不可以传数据request.getRequestDispatcher("/megustas/login.jsp").forward(request, response);} else {// 登陆成功// 判断是否勾选自动登陆if ("true".equals(request.getParameter("autologin"))) {// 用户勾选了 自动登陆// 将用户名和密码 以cookie形式写给客户端Cookie cookie = new Cookie("autologin", URLEncoder.encode(username, "utf-8")+ "." + password);cookie.setMaxAge(60 * 60);cookie.setPath("/megustas");response.addCookie(cookie);}// 将成功信息 保存Sessionrequest.getSession().setAttribute("user", user); // 表示已经登陆response.sendRedirect("/megustas/demo4/welcome.jsp");}} catch (SQLException e) {e.printStackTrace();}}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}}
欢迎界面
<body>
<!-- 根据session中是否存在user对象,判断用户是否登陆 -->
<c:if test="${empty user}"><h1>您还未登陆!去<a href="/megustas/demo4/login.jsp">登陆</a></h1>
</c:if>
<c:if test="${not empty user}"><h1>登陆成功, ${user.username }</h1>
</c:if>
</body>
加密demo
public class DigestUtils {/*** 使用md5的算法进行加密* * @param plainText* 加密原文* @return 加密密文*/public static String md5(String plainText) {byte[] secretBytes = null;try {secretBytes = MessageDigest.getInstance("md5").digest(plainText.getBytes());} catch (NoSuchAlgorithmException e) {throw new RuntimeException("没有md5这个算法!");}return new BigInteger(1, secretBytes).toString(16);// 将加密后byte数组// 转换16进制表示}}
自动登录功能
AutoLoginFilter 在什么情况下需要自动登录 ??
1、当前用户必须未登陆
2、存在自动登录cookie信息
- 自动登陆过滤器,过滤页面一定不包括登录和注册页面
配置(配置自动登录的过滤器,在进入欢迎界面之前检查是否登录)
<filter><filter-name>AutoLoginFilter</filter-name><filter-class>cn.megustas.demo4.AutoLoginFilter</filter-class></filter><filter-mapping><filter-name>AutoLoginFilter</filter-name><!-- 访问welcome.jsp 时完成自动登录 --><url-pattern>/demo4/welcome.jsp</url-pattern></filter-mapping>
Filter
public class AutoLoginFilter implements Filter {@Overridepublic void destroy() {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {// 1、判断当前用户是否已经登录HttpServletRequest httpServletRequest = (HttpServletRequest) request;if (httpServletRequest.getSession().getAttribute("user") == null) {// 未登录// 2、判断autologin对应cookie 是否存在 ---- 将cookie 查询写为工具类Cookie cookie = CookieUtils.findCookie(httpServletRequest.getCookies(), "autologin");if (cookie != null) {// 找到了自动登录cookieString username = cookie.getValue().split("\\.")[0];// 如果用户名中文,需要解密username = URLDecoder.decode(username, "utf-8");String password = cookie.getValue().split("\\.")[1];// 获得就是md5 加密密码,此处无需加密// 登录逻辑String sql = "select * from user where username=? and password = ?";Object[] args = { username, password };QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());try {User user = queryRunner.query(sql, new BeanHandler<User>(User.class), args);if (user != null) {httpServletRequest.getSession().setAttribute("user",user);}chain.doFilter(httpServletRequest, response);} catch (SQLException e) {e.printStackTrace();}} else {// 没有自动登录信息chain.doFilter(httpServletRequest, response);}} else {// 已经登录,不需要自动登录chain.doFilter(httpServletRequest, response);}}@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}}
其中调用的Utils,cookie查询
public class CookieUtils {// 在cookies 数组中 查找指定name 的cookiepublic static Cookie findCookie(Cookie[] cookies, String name) {if (cookies == null) {// cookie 不存在return null;} else {// cookie 存在for (Cookie cookie : cookies) {if (cookie.getName().equals(name)) {// 找到return cookie;}}// 没有找到return null;}}
}
注意
(1)程序中调用的一些简单的工具包,功能在之前的博客都有实现,故不再赘述
(2)转发和重定向使用
1、使用转发,通过request.setAttribute 传递数据给 页面,路径不要写/工程名 ;
request.setAttribute("msg", "用户名或者密码错误"); request.getRequestDispatcher("/megustas/login.jsp").forward(request, response);
2、使用重定向,不能用request传递数据,路径要写/工程名
response.sendRedirect("/megustas/demo4/welcome.jsp");
3、自动登录过滤器,过滤页面一定不包括登录和注册页面
自动登陆案例问题:
1、 如果用户名中文怎么办?
insert into user values(null,'小红','123','user');
解决方案:保存cookie时进行手动编码 URL编码
生成cookie 时 new Cookie(URLEncoder.encode(用户名,"utf-8"));
—— LoginServlet
读取cookie时, 对用户进行解码 URLDecoder.decode(用户名,"utf-8");
—- AutoLoginFilter
2、 中文名和密码安全问题
* cookie 是一个文本类型文件,内容非常容易泄露
实际开发中数据库中密码和cookie中密码 都应该加密后保存 —- 单向加密算法 MD5
* MySQL 提供md5 方法进行加密
将数据进行md5 加密
update user set password = md5(password) ;
MD5 破解 —– 多对一映射算法 (运行两个不同明文 产生相同密文 概率很低) —- http://www.cmd5.com/
流程:初次login.jsp进行登录,跳转到welcome.jsp
关闭浏览器,直接登录welcome.jsp,将会由自动登录环节完成