0
点赞
收藏
分享

微信扫一扫

Tomcat源码学习--Cookie创建和销毁

青乌 2022-08-26 阅读 99


上一篇博客​​Tomcat源码学习--Session创建销毁​​中我们学习了Session创建、使用和销毁的操作,接下来我们看看Tomcat中对Cookie是如何做处理的。首先我们要了解Cookie是由浏览器创建、管理和销毁操作的,Tomcat只能获取浏览器请求过来的cookie值,或者创建cookie。

一、获取Cookie

1、通过request获取cookie

Cookie [] cookies = request.getCookies();

在Request的外观类RequestFacade类中提供getCookies()方法

@Override
public Cookie[] getCookies() {

if (request == null) {
throw new IllegalStateException(
sm.getString("requestFacade.nullRequest"));
}

Cookie[] ret = null;

/*
* Clone the returned array only if there is a security manager
* in place, so that performance won't suffer in the non-secure case
*/
if (SecurityUtil.isPackageProtectionEnabled()){
ret = AccessController.doPrivileged(
new GetCookiesPrivilegedAction());
if (ret != null) {
ret = ret.clone();
}
} else {
ret = request.getCookies();
}

return ret;
}

在tomcat的类Rquest中提供getCookies()方法,cookiesConverted会将浏览器发送过来的cookie数据进行解析

@Override
public Cookie[] getCookies() {
if (!cookiesConverted) {
convertCookies();
}
return cookies;
}

covertCookies中会对cookie进行转换并返回

protected void convertCookies() {
if (cookiesConverted) {
return;
}

cookiesConverted = true;

if (getContext() == null) {
return;
}
//解析cookie,浏览器将cookie数据添加到header中发送到后端
parseCookies();

ServerCookies serverCookies = coyoteRequest.getCookies();
CookieProcessor cookieProcessor = getContext().getCookieProcessor();

int count = serverCookies.getCookieCount();
if (count <= 0) {
return;
}

cookies = new Cookie[count];
//获取解析后的cookie并组装后返回
int idx=0;
for (int i = 0; i < count; i++) {
ServerCookie scookie = serverCookies.getCookie(i);
try {
/*
we must unescape the '\\' escape character
*/
Cookie cookie = new Cookie(scookie.getName().toString(),null);
int version = scookie.getVersion();
cookie.setVersion(version);
scookie.getValue().getByteChunk().setCharset(cookieProcessor.getCharset());
cookie.setValue(unescape(scookie.getValue().toString()));
cookie.setPath(unescape(scookie.getPath().toString()));
String domain = scookie.getDomain().toString();
if (domain!=null)
{
cookie.setDomain(unescape(domain));//avoid NPE
}
String comment = scookie.getComment().toString();
cookie.setComment(version==1?unescape(comment):null);
cookies[idx++] = cookie;
} catch(IllegalArgumentException e) {
// Ignore bad cookie
}
}
if( idx < count ) {
Cookie [] ncookies = new Cookie[idx];
System.arraycopy(cookies, 0, ncookies, 0, idx);
cookies = ncookies;
}
}

parseCookies()方法会将浏览器发送过来的header中的cookie提取出来

protected void parseCookies() {
if (cookiesParsed) {
return;
}

cookiesParsed = true;

ServerCookies serverCookies = coyoteRequest.getCookies();
serverCookies.setLimit(connector.getMaxCookieCount());
CookieProcessor cookieProcessor = getContext().getCookieProcessor();
cookieProcessor.parseCookieHeader(coyoteRequest.getMimeHeaders(), serverCookies);
}

CookieProcessor的实现类Rfc6265CookieProcessor会根据一定的规则对头部的cookie解析并转换为Cookie数组

在浏览器发送到后台的数据中Cookie是一个字符串,通过;分好进行数据分割。


Tomcat源码学习--Cookie创建和销毁_ide


@Override
public void parseCookieHeader(MimeHeaders headers,
ServerCookies serverCookies) {

if (headers == null) {
// nothing to process
return;
}

// process each "cookie" header
//查找头部中key为Cookie的值
int pos = headers.findHeader("Cookie", 0);
while (pos >= 0) {
MessageBytes cookieValue = headers.getValue(pos);

if (cookieValue != null && !cookieValue.isNull() ) {
if (cookieValue.getType() != MessageBytes.T_BYTES ) {
if (log.isDebugEnabled()) {
Exception e = new Exception();
// TODO: Review this in light of HTTP/2
log.debug("Cookies: Parsing cookie as String. Expected bytes.", e);
}
cookieValue.toBytes();
}
if (log.isDebugEnabled()) {
log.debug("Cookies: Parsing b[]: " + cookieValue.toString());
}
ByteChunk bc = cookieValue.getByteChunk();

Cookie.parseCookie(bc.getBytes(), bc.getOffset(), bc.getLength(),
serverCookies);
}

// search from the next position
pos = headers.findHeader("Cookie", ++pos);
}
}

这样就可以从头部中获取所有的Cookie数据,并返回Cookie的数组集合。

二、Cookie销毁

cookie会有日期生存时间,cookie的销毁操作是浏览器来实现的,tomcat无法完成cookie销毁操作。

三、Cookie创建


cookie创建简单来说就是tomcat通过设置一定的key、value和生存时间让浏览器来创建cookie。


调用HttpServletResponse的addCookie来创建cookie


Cookie testCookie = new Cookie("test", "test");
testCookie.setMaxAge(30);
response.addCookie(testCookie);

HttpServletResponse的实现类ResponseFacade调用addCookie

@Override
public void addCookie(Cookie cookie) {

if (isCommitted()) {
return;
}

response.addCookie(cookie);

}

Response的addCookie中会将cookie对象转为String数据并添加到头部中


@Override
public void addCookie(final Cookie cookie) {

// Ignore any call from an included servlet
if (included || isCommitted()) {
return;
}

cookies.add(cookie);
//将cookie对象转为String头部数据
String header = generateCookieString(cookie);
//if we reached here, no exception, cookie is valid
// the header name is Set-Cookie for both "old" and v.1 ( RFC2109 )
// RFC2965 is not supported by browsers and the Servlet spec
// asks for 2109.
//将cookie值添加到头部中
addHeader("Set-Cookie", header, getContext().getCookieProcessor().getCharset());
}









举报

相关推荐

0 条评论