做web开发不可避免会涉及到cookie和session,http的请求是无状态的,这里总结下平时梳理的关于cookie和session的相关知识.
Http是无状态的协议,现在的web应用越来越复杂,在每次的网络请求中,需要能够携带一些用户信息.最常见的是登录网站的时候,登录之后再次访问网站,服务器端需要知道这个用户是否是登录状态.于是就有了cookie和Session. cookie存储在客户端,用来保存会话信息,每次请求服务器端的时候会携带cookie请求,服务器端从cookie中获取到状态信息 而Session则由服务器端产生并保存在服务器端,服务器端从cookie中取到状态信息之后,需要针对这些信息做验证,这个验证信息就来自于服务器端的Session.
cookie
cookie的写入
cookie由服务端写入,cookie本身是一个字符串,但这个字符串是有格式的,有键值对组成. 如下是一个请求中的header信息:
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8,zh;q=0.7,zh-CN;q=0.6
Connection: keep-alive
Cookie: _ga=GA1.2.486261727.1542307321; _gid=GA1.2.414078029.1542595624; s.k=n8-121-175c472a34a-f1bf-45c6-916a-4d8b7121422b; _gat=1
Host: www.baidu.com
Referer: https://www.baidu.com/page/approval-hub/user-permission
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36
每个cookie都有自己的属性,包括Domain,Path,ExpireTime,Size等,在设置cookie时可以设置这些属性
cookie的传递
客户端向服务端发起请求时,会先检查本地是否存在该域名下的cookie,如果存在,则将cookie加入到请求header中.一个URL包含域名(domain)和路径(path),这两个选项决定cookie是否要添加到header中.如果cookie在写入的时候未设置域名和路径,那么domain的默认值将是设置这个cookie的网页所在的域名,path默认为设置这个cookie的网页所在的目录.
跨域的cookie传递
cookie
session
Java应用中的Session实现
web应用运行在servlet容器中,servlet就是处理web请求的.Session对应的java实现类为HttpSession.Servlet容器通过HttpSession接口来实现Http客户端和Http服务端的Session.
HttpServletRequest是HTTP servlet的请求实体类,由servlet容器创建.通过HttpServletRequest.getSession(boolean create);
可以获得当前请求关联的Session,如果不存在Session,则创建一个.
在Tomcat中,ApplicationHttpRequest是HttpServletRequest的包装类.StandardSessionFacade则是HttpSession的实现类.其中getSession的实现如下:
/**
* Return the session associated with this Request, creating one
* if necessary and requested.
*
* @param create Create a new session if one does not exist
*/
@Override
public HttpSession getSession(boolean create) {
if (crossContext) {//标示web应用的路径是否一样
// There cannot be a session if no context has been assigned yet
if (context == null)
return null;
// Return the current session if it exists and is valid
if (session != null && session.isValid()) {
return session.getSession();
}
HttpSession other = super.getSession(false);
if (create && (other == null)) {
// First create a session in the first context: the problem is
// that the top level request is the only one which can
// create the cookie safely
other = super.getSession(true);
}
if (other != null) {
Session localSession = null;
try {
localSession =
context.getManager().findSession(other.getId());//根据sessionId获取上下文中的HttpSession
if (localSession != null && !localSession.isValid()) {
localSession = null;//若本地session过期,则置为null
}
} catch (IOException e) {
// Ignore
}
if (localSession == null && create) {
localSession =
context.getManager().createSession(other.getId());//若本地session不可用,根据指定的sessionid创建一个新的session
}
if (localSession != null) {
localSession.access();
session = localSession;
return session.getSession();
}
}
return null;
} else {
return super.getSession(create);
}
}
分布式Session管理
现在的服务器基本都是分布式系统,也就是说,一个应用会同时部署在多台机器上,根据负载均衡策略的不同,一个用户的请求可能会发送到不同的服务器上,那么就带来了一个问题:如果Session存储在服务器,当一个用户的请求被分发到不同的服务器上时,两次的请求在服务器端的状态信息就会存在不一致的情况.对于需要验证登录信息的页面,就会导致用户反复登录. 所以现在的系统设计需要对Session信息做集中管理,独立于web容器. 在Spring框架下,这个问题有一个很好的解决方案~:spring-session
todo:spring-session实现
参考:
Session机制详解以及Session的相关应用
spring-session文档
聊一聊 cookie
cookie知识点整理
cookie的domain写入(指定的时候/默认值)
cookie的各个属性值和含义
服务端和客户端设置cookie
cookie的修改和删除
跨域设置cookie
xhr
cors–跨域cookie的传递
怎样跨域传递cookie?怎样算跨域
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain 定义网络文件的类型和网页的编码,决定文件接收方将以什么形式、什么编码读取这个文件 application/x-www-form-urlencoded form表单被编码为key/value格式发送到服务器 multipart/form-data 需要在表单中进行文件上传时,就需要使用该格式 application/json;charset=UTF-8 数据以json格式传输
http body和request