文章目录
浅谈cookie、session、Token
HTTP是无状态协议,它不对之前发生过的请求和响应的状态进行管理。为了克服这一缺点,所以引入了cookie,session技术。当然无状态协议也有优点,由于不必保存状态,所以可以减少服务器的CPU及内存资源的消耗。
关于cookie和session其实都是为了记录用户状态,它们的区别是cookie将状态信息保存在浏览器上,而session是将信息保存在服务器上。session是依赖于cookie的,因为它需要cookie来保存sessionID.本质上来说两者是相同的。session在一定程度上保证了用户信息的安全,但是cookie和session也都是可以被伪造的。
1 Cookie
(1)定义:
Cookies 是存储在客户端计算机上的文本文件(key-value),并保留了用户的各种跟踪信息。
客户端向服务器发起请求,如果服务器需要记录该用户状态,就会通过响应报文中的一个叫做Set-Cookie
的首部字段信息,通知客户端保存Cookie. 当下次客户端 再向该服务器发送请求时,客户端会自动在请求报文中加入Cookie值后发送出去。而服务器在得到客户端发送过来的Cookie后,会去检查是哪一个客户端发来的请求,然后对比服务器上的记录,得到该客户端之前的状态信息。
(2)作用:
会话保持,如完成用户的登录与状态保持。
服务器设置Cookies 通常设置在HTTP 头信息中:
HTTP/1.1 200 OK
Date: Fri, 04 Feb 2000 21:03:38 GMT
Server: Apache/1.3.9
Set-Cookie: name=xyz; expires=Friday, 04-Feb-07 22:03:38 GMT;
path=/; domain=bit.com
Connection: close
Content-Type: text/html
如果用户的浏览器指向任何匹配该Cookie 的路径和域的页面,它会重新发送Cookie 到服务器。浏览器的请求头信息
GET / HTTP/1.0
Connection: Keep-Alive
User-Agent: Mozilla/4.6 (X11; I; Linux 2.2.6-15apmac ppc)
Host: zink.demon.co.uk:1126
Accept: image/gif, */*
Accept-Encoding: gzip
Accept-Language: en
Accept-Charset: iso-8859-1,*,utf-8
Cookie: name=xyz
Servlet 能够通过请求方法 request.getCookies() 访问Cookie,该方法将返回一个Cookie 对象的数组
Cookie[] ret=req.getCookies();
(3)Servlet 操作cookie方法
public void setDomain(String pattern)
:该方法设置cookie 适用的域。
public String getDomain()
:该方法获取cookie 适用的域。
public void setMaxAge(int expiry)
:该方法设置cookie 过期的时间(以秒为单位)。如果不这样设置,cookie 只会在当前session 会话中持续有效(即当关闭浏览器后,连接就会失效)。
public int getMaxAge()
:该方法返回cookie 的最大生存周期(以秒为单位),默认情况下,-1 表示cookie 将持续下去,直到浏览器关闭。
public String getName()
:该方法返回cookie 的名称。名称在创建后不能改变。
public void setValue(String newValue)
:该方法设置与cookie 关联的值。
public String getValue()
:该方法获取与cookie 关联的值。
public void setPath(String uri)
:该方法设置cookie 适用的路径。如果不指定路径,与当前页面相同目录下的(包括子目录下的)所有URL 都会返回cookie。
public String getPath()
:该方法获取cookie 适用的路径。
(4)服务端设置cookie:
@WebServlet("/set-cookie")
public class CookieDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 手动设置状态头的方式设置
//resp.setHeader("Set-Cookie", "mingzi=peixinchen");
Cookie cookie = new Cookie("name","glp");
cookie.setMaxAge(60);
resp.addCookie(cookie);
}
}
(5)服务端获取cookie:
String cookie = req.getHeader("Cookie");
代码示例:
@WebServlet("/print-cookie")
public class PrintCookie extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/plain; charset=utf-8");
PrintWriter writer = resp.getWriter();
// 手动从请求头中获取
String cookie = req.getHeader("Cookie");
if (cookie == null) {
System.out.println("没有设置 Cookie");
writer.println("没有设置 Cookie");
} else {
System.out.println(cookie);
writer.println(cookie);
}
}
}
2 Session
(1)定义:
session是依赖Cookie实现的,是存储在服务器上的文本文件,并保留了用户的各种跟踪信息。
session 是浏览器和服务器会话过程中,服务器分配的一块储存空间。服务器默认为浏览器在cookie中设置 sessionid,浏览器在向服务器请求过程中传输 cookie 包含 sessionid ,服务器根据 sessionid 获取出会话中存储的信息,然后确定会话的身份信息。
(2)作用:
会话保持,如完成用户的登录与状态保持,因为在服务器端,所以相对安全一些
(3) Servlet 操作session方法
HttpSession 对象
- Servlet 还提供了
HttpSession 接口
,该接口提供了一种跨多个页面请求或访问网站时识别用户以及存储有关用户信息的方式。 - Servlet 容器使用这个接口来创建一个HTTP 客户端和HTTP 服务器之间的session会话。会话持续一个指定的时间段,跨多个连接或页面请求。
- 我们可以通过调用HttpServletRequest 的公共方法getSession() 来获取
HttpSession 对象,如下所示:HttpSession session = request.getSession();
(HttpSession 对象中可用的几个重要的方法:
public Object getAttribute(String name)
:该方法返回在该session 会话中具有指定名称的对象,如果没有指定名称的对象,则返回null。
public void setAttribute(String name, Object value)
:该方法使用指定的名称绑定一个对象到该session 会话。
public Enumeration getAttributeNames()
:该方法返回String 对象的枚举,String 对象包含所有绑定到该session 会话的对象的名称。
public long getCreationTime()
:该方法返回该session 会话被创建的时间,自格林尼治标准时间1970 年1 月1 日午夜算起,以毫秒为单位。
public String getId()
:该方法返回一个包含分配给该session 会话的唯一标识符的字符串。
public long getLastAccessedTime()
:该方法返回客户端最后一次发送与该session 会话相关的请求的时间自格林尼治标准时间1970 年1 月1 日午夜算起,以毫秒为单位。
public int getMaxInactiveInterval()
: 该方法返回Servlet 容器在客户端访问时保持session 会话打开的最大时间间隔,以秒为单位。
public void invalidate()
:该方法指示该session 会话无效,并解除绑定到它上面的任何对象。
public boolean isNew()
:如果客户端还不知道该session 会话,或者如果客户选择不参入该session 会话,则该方法返回true。
public void removeAttribute(String name)
:该方法将从该session 会话移除指定名称的对象。
public void setMaxInactiveInterval(int interval)
:该方法在Servlet 容器指示该session 会话无效之前,指定客户端请求之间的时间,以秒为单位。
(4)服务端设置session:
HttpSession session = req.getSession();
session.setAttribute("user", user);
代码示例:
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
HttpSession session = req.getSession();
resp.setContentType("text/plain; charset=utf-8");
PrintWriter writer = resp.getWriter();
User user = User.login(username, password);
if (user != null) {
// 表示认证成功(登陆成功)
// 1. 把 User 对象放入 Session 服务器中
session.setAttribute("user", user);
writer.println("登陆成功,欢迎 " + user.username);
} else {
writer.println("没有这个用户");
}
}
(5)服务端获取session:
HttpSession session = req.getSession();
User user = (User)session.getAttribute("user");
代码示例:
@WebServlet("/who")
public class WhoAmIServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/plain; charset=utf-8");
PrintWriter writer = resp.getWriter();
HttpSession session = req.getSession();
User user = (User)session.getAttribute("user");
if (user == null) {
writer.println("I don't know who you are");
} else {
writer.println("you are " + user.username);
}
}
}
3 cookie与session区别
- 存储位置与安全性:cookie数据存放在客户端上,安全性较差,session数据放在服务器上,安全性相对更高;
- 存储空间:单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie,session无此限制。
- 占用服务器资源:session保存在服务器上,当访问增多时会占用服务器性能,考虑到服务器性能方面,此时应当使用cookie。
4 Token
Token:Token是在客户端频繁向服务端请求数据,服务端频繁的去数据库查询用户名和密码并进行对比,判断用户名和密码正确与否,并作出相应提示,在这样的背景下,Token便应运而生。
Token的定义:Token是服务端生成的一串字符串,以作为客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。
使用Token的目的:Token的目的是为了减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮。
Token 是在服务端产生的。如果前端使用用户名/密码向服务端请求认证,服务端认证成功,那么在服务端会返回 Token 给前端。前端可以在每次请求的时候带上 Token 证明自己的合法地位。
(1)session与token区别
- session机制存在服务器压力增大,CSRF跨站伪造请求攻击,扩展性不强等问题;
- session存储在服务器端,token存储在客户端
- token提供认证和授权功能,作为身份认证,token安全性比session好;
- session这种会话存储方式方式只适用于客户端代码和服务端代码运行在同一台服务器上,token适用于项目级的前后端分离(前后端代码运行在不同的服务器下)