Cookie是什么?
- 类型为“小型文本文件”,是某些网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息。
- 原理: 一个 Web 站点可能会为每一个访问者产生一个唯一的ID, 然后以 Cookie 文件的形式保存在每个用户的机器上。如果使用浏览器访问 Web, 会看到所有保存在硬盘上的 Cookie。在这个文件夹里每一个文件都是一个由“名/值”对组成的文本文件,另外还有一个文件保存有所有对应的 Web 站点的信息。在这里的每个 Cookie 文件都是一个简单而又普通的文本文件。透过文件名, 就可以看到是哪个 Web 站点在机器上放置了Cookie(当然站点信息在文件里也有保存)
cookies组成部分
Cookie是一段不超过4KB的小型文本数据,由一个名称(Name)、一个值(Value)
Expires属性:设置Cookie的生存期
Path属性:定义了Web站点上可以访问该Cookie的目录
Domain属性:指定了可以访问该 Cookie 的 Web 站点或域
Secure属性:指定是否使用HTTPS安全协议发送Cookie
HTTPOnly 属性 :用于防止客户端脚本通过document.cookie属性访问Cookie,
验证使用方法:
- 导入Httpservlet-api包
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
配置:
- 结构:
tomcat 配置
web.xml配置:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>cookies</servlet-name>
<servlet-class>cookies.CookiesTest01</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>cookies</servlet-name>
<url-pattern>/cookies</url-pattern>
</servlet-mapping>
</web-app>
ok!确保能够tomcat 能够跑起来之后,就进行正式的环节:
编写程序
cookie是由名称、内容、作用路径、作用域、协议、生存周期组成----见名知意
Cookies 方法如下:
此处使用doGet方法,doPost效果一样,只是请求方式和请求数据的大小限制问题、安全问题等不同,读者可以查阅相关资料。
package cookies;
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.xml.crypto.Data;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
public class CookiesTest01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 处理字符乱码问题
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
// 设置访问形式
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter(); //返回前端写出
// 获取浏览器传输的cookies
Cookie[] cookies = req.getCookies();
System.out.println("获取的cookie"+cookies);
// 判断用户是否是第一次得到cookies
if (cookies!=null){
out.write("上次访问的信息是:");
for (int i=0;i<cookies.length;i++) {
Cookie cookie = cookies[i];
// System.out.println("_______不为空的cookies 为_______:"+cookie.getName().toString());
if (cookie.getName().equals("lastAccessTime")) {
long lastAccessTime = Long.parseLong(cookie.getValue()); //获取cookies的值
// System.out.println(lastAccessTime);
System.out.println(cookie.isHttpOnly());
Date date = new Date(lastAccessTime);
// System.out.println(date);
out.write(date.toLocaleString() + " cookies 美妙!! ");
System.out.println(date.toLocaleString());
}
}
}else {
out.write("这是您第一次访问本站\n");
}
//用户访问过之后重新设置用户的访问时间,存储到cookie中,然后发送到客户端浏览器
Cookie cookie = new Cookie("lastAccessTime", System.currentTimeMillis()+""); //System.currentTimeMillis()+"" 《-中间不能加其他字符
resp.addCookie(cookie);
out.write("This is addCookies Address: "+String.valueOf(cookie));
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
}
当存在cookies时会进入for循环,寻找上次的cookie时间
cookies 作用时间设置
Cookie cookie = new Cookie("lastAccessTime", System.currentTimeMillis()+""); //System.currentTimeMillis()+"" 《-中间不能加其他字符
//设置Cookie的有效期为1天
cookie.setMaxAge(24*60*60);
resp.addCookie(cookie);
cookies设置:
HttpOnly属性,HttpOnly属性很重要,如果您在cookie中设置了HttpOnly属性,那么通过js脚本(document.cookie)将无法读取到cookie信息,这样能一定程度上的防止XSS攻击
Cookie cookie = new Cookie("lastAccessTime", System.currentTimeMillis()+""); //System.currentTimeMillis()+"" 《-中间不能加其他字符
//设置Cookie的有效期为1天
cookie.setMaxAge(24*60*60);
cookie.setHttpOnly(true);
resp.addCookie(cookie);
方法介绍到此结束,如果在过程中有什么问题,可以查阅资料或者留言
=========================================
cookies底层是怎么实现的了?一直很头疼,于是就开了底层的方法:
当获取cookie的值后,比较 isToken和name 是否为空,抛出异常,给name 和value 赋值
public Cookie(String name, String value) {
if (name == null || name.length() == 0) {
throw new IllegalArgumentException(
lStrings.getString("err.cookie_name_blank"));
}
if (!isToken(name) ||
name.equalsIgnoreCase("Comment") || // rfc2019
name.equalsIgnoreCase("Discard") || // 2019++
name.equalsIgnoreCase("Domain") ||
name.equalsIgnoreCase("Expires") || // (old cookies)
name.equalsIgnoreCase("Max-Age") || // rfc2019
name.equalsIgnoreCase("Path") ||
name.equalsIgnoreCase("Secure") ||
name.equalsIgnoreCase("Version") ||
name.startsWith("$")) {
String errMsg = lStrings.getString("err.cookie_name_is_token");
Object[] errArgs = new Object[1];
errArgs[0] = name;
errMsg = MessageFormat.format(errMsg, errArgs);
throw new IllegalArgumentException(errMsg);
}
this.name = name;
this.value = value;
}
一步步下去之后,还是回到了Httpservlet,感觉就是高耦合,一步步联系,各个类相互使用,有兴趣的同学可以看看23重设计模式
下面本人在这过程中遇到的一些问题及解决思路:有兴趣的读者可以批评指导:
第一次写实现类的时候因为System.currentTimeMillis()没有加任何东西报错,也没有任何提示性错误,所以自作主张的加上了System.currentTimeMillis()+“1345”
运行之后竟然不能输出到页面???
纳闷的我,就在debug之路上越走越远。
Cookie cookie = new Cookie("lastAccessTime", System.currentTimeMillis()+"12313"); //System.currentTimeMillis()+"" 《-中间不能加其他字符
//设置Cookie的有效期为1天
cookie.setMaxAge(24*60*60);
cookie.setHttpOnly(true);
resp.addCookie(cookie);
out.write("This is addCookies Address: "+String.valueOf(cookie));
- [1 ] 查看cookie设置的name并没有添加在cookie上
默默的查看request信息,ok,没毛病,是读取进来的,老铁。
再查看cookie的值,是请求进来的,硬着头皮看下去,坚强
最后辗转反侧,终于发现了,是有一个无效值,程序根本没有执行到
Cookie cookie = new Cookie(“lastAccessTime”, System.currentTimeMillis()+“12313”);
真相清晰了,就是这语句有问题,查阅资料之后发现这个中间不能有值,我当时是想检验是否成功,傻里傻气的加上,导致了这个debug
Cookie cookie = new Cookie("lastAccessTime", System.currentTimeMillis()+""); //System.currentTimeMillis()+"" 《-中间不能加其他字符
package cookies;
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.xml.crypto.Data;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
public class CookiesTest01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 处理字符乱码问题
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
// 设置访问形式
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter(); //返回前端写出
// 获取浏览器传输的cookies
Cookie[] cookies = req.getCookies();
System.out.println(cookies);
// 判断用户是否是第一次得到cookies
if (cookies!=null){
out.write("上次访问的信息是:");
for (int i=0;i<cookies.length;i++){
Cookie cookie = cookies[i];
System.out.println("不为空的cookies 为:=="+cookie.getName());
if (cookie.getName().equals("lastAccessTime")){
long lastAccessTime = Long.parseLong(cookie.getValue()); //获取cookies的值
System.out.println(lastAccessTime);
Date date = new Date(lastAccessTime);
System.out.println(date);
out.write(date.toLocaleString());
}
}
}else {
out.write("这是您第一次访问本站");
}
//用户访问过之后重新设置用户的访问时间,存储到cookie中,然后发送到客户端浏览器
Cookie cookie = new Cookie("lastAccessTime", System.currentTimeMillis()+"123 ");
System.out.println("添加的cookie:"+cookie.getName());
resp.addCookie(cookie);
out.write("这是返回设置的cookies时间"+cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
}
O了,希望这篇文章能够帮助到您!@_^_@
觉得不错的话,欢迎点赞关注♥♥♥