JavaWeb实现记住密码功能(使用Cookie)
1、Cookie知识点
-
cookie介绍
- 背景:HTTP协议作是⽆状态协议,⽆状态指每次request请求之前是相互独⽴的,当前请求 并不会记录它的上⼀次请求信息。 存在这样的问题,既然⽆状态,那完成⼀套完整的业务逻 辑,需要发送多次请求,那么怎么标识这些请求都是同个浏览器操作呢?
- 解决⽅案:
- 浏览器发送request请求到服务器,服务器除了返回请求的response之外,还给请求分 配⼀个唯⼀标识ID和response⼀并返回给浏览器
- 服务器在本地创建⼀个map结构,专⻔以key-value存储这个ID标识和浏览器的关系
- 当浏览器的第⼀次请求后已经分配⼀个ID,当第⼆次访问时会⾃动带上这个标识ID,服 务会获取这个标识ID去map⾥⾯找上⼀次request的信息状态且做对应的更新操作 服务 端⽣成这个全局的唯⼀标识,传递给客户端⽤于标记这次请求就是cookie; 服务器创建 的那个map结构就是session
- cookies由服务端⽣成,⽤于标记客户端的唯⼀标识,在每次⽹络请求中,都会被传送。
- session服务端⾃⼰维护的⼀个map数据结构,记录key-Object上下⽂内容状态
- 核⼼:它⽤于告知服务端两个请求是否来⾃同⼀浏览器,如保持⽤户的登录状态。 Cookie使基于⽆状态的HTTP协议记录稳定的状态信息成为了可能。 浏览器查看多个站 点的cookie
-
cookie的属性
- Name : 名称
- Value : 值
- Domain:表示当前cookie所属于哪个域或⼦域下⾯
- Expires/Max-age:表示了cookie的有效期,是⼀个时间,过了这个时间,该cookie就失效了
- Path:表示cookie的所属路径。
- size: ⼤⼩,多数浏览器都是4000多个字节
- http-only: 表示这个cookie不能被客户端使⽤js读取到,是不公开的cookie (chrome调试器的console中输⼊document.cookie将得不到标记为HttpOnly的字段)
- Secure: 标记为 Secure 的Cookie只应通过被HTTPS协议加密过的请求发送给服务端, 从 Chrome 52 和 Firefox 52 开始,不安全的站点(http:)⽆法使⽤Cookie的 Secure 标记 SameSite(特有的,可以忽略)
-
Cookie的缺陷
- cookie会被附加在每个HTTP请求中,增加了流量。
- 在HTTP请求中的cookie是明⽂传递的,所以安全性成问题,除⾮⽤HTTPS
- Cookie的⼤⼩有限制,对于复杂的存储需求来说不满⾜
- 如果cookie泄露,你猜猜会发⽣什么问题?
-
浏览器允许每个域名所包含的cookie数量?
-
多数浏览器允许最多是50个,部分浏览器是30或者20;
-
满后会有多种剔除策略,⽐如LRU,权重等
-
-
Cookie的现状:
-
Cookie曾⼀度⽤于客户端数据的存储,因当时并没有其它合适的存储办法⽽作为唯⼀的存储⼿段
-
现代浏览器开始⽀持各种各样的存储⽅式,Cookie渐渐被少⽤了,新的浏览器API已经允许开发者 直接将数据存储到本地,⽐如localStorage、SessionStorage等 参考:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Cookies
-
2、项目实战
1、编写前端 login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/login" method="post">
用户名:<input type="text" name="username" value="${cookiename }"/><br>
密码:<input type="password" name="pwd" value="${cookiepwd }"/><br>
<input type="submit" value="登录"/>
</form>
<hr>
用户名:${username }
密码:${pwd }<br>
<c:if test="${username!=null }">
<a href="${pageContext.request.contextPath }/logoutController">退出登录</a>
</c:if>
</body>
</html>
2、编写后端,实现cookie的记录与取值
2.1 loginController.java
package cn.yz123123.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/login")
public class loginController extends HttpServlet{
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
req.setAttribute("username", username);
String pwd = req.getParameter("pwd");
req.setAttribute("pwd", pwd);
Cookie cookiename = new Cookie("cookiename", username);
cookiename.setMaxAge(1000000);
Cookie cookiepwd = new Cookie("cookiepwd", pwd);
cookiepwd.setMaxAge(1000000);
resp.addCookie(cookiename);
resp.addCookie(cookiepwd);
req.getRequestDispatcher("/cookieController").forward(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
2.2、CookieController.java
package cn.yz123123.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/cookieController")
public class CookieController extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie[] cookies = request.getCookies();
for(Cookie cookie:cookies){
if(cookie.getName().equals("cookiename")){
request.getServletContext().setAttribute("cookiename", cookie.getValue());
}
if(cookie.getName().equals("cookiepwd")){
request.getServletContext().setAttribute("cookiepwd", cookie.getValue());
}
}
request.getRequestDispatcher("/login.jsp").forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
2.3 logoutController
package cn.yz123123.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/logoutController")
public class logoutController extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getSession().invalidate();
request.getRequestDispatcher("/login").forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}