Session & Cookies

本文介绍了会话管理技术的基础概念,包括会话(session)、Cookie及其应用案例,以及session的工作原理和API使用。通过实例展示了如何利用Cookie记录访问时间和浏览历史,并使用session实现购物车功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一 什么是绘话

会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话。

二 什么是Cookie

2.1什么是cookie

Cookie是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。这样,web资源处理的就是用户各自的数据了。

如上图所示,浏览器首次访问服务器的时候是不带cookie的,到服务器端以后,客户端创建cookies之后,随着请求的响应流带到客户端浏览器,浏览器把回来的cookie放到缓存中,当下一次请求同样基地址路径的时候,客户端会带着cookies到服务器,服务器就可以通过浏览器缓存技术取到客户端首次访问的值。

2.2 Cookie的传输媒介

javax.servlet.http.Cookie类用于创建一个Cookie,response接口中定义了一个addCookie方法,它用于在其响应头中增加一个相应的Set-Cookie头字段。 同样,request接口中也定义了一个getCookies方法,它用于获取客户端提交的Cookie。

2.3 Cookie的API

public Cookie(String name,String value)

setValue与getValue方法

setMaxAge与getMaxAge方法 (秒)

setPath与getPath方法

setDomain与getDomain方法

getName方法

2.4 Cookie详解

(1) 一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称(NAME)和设置值(VALUE)。

(2) 一个WEB站点可以给一个WEB浏览器发送多个Cookie,一个WEB浏览器也可以存储多个WEB站点提供的Cookie。

(3) 浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB。

(4) 如果创建了一个cookie,并将他发送到浏览器,默认情况下它是一个会话级别的cookie(即存储在浏览器的内存中),用户退出浏览器之后即被删除。若希望浏览器将该cookie存储在磁盘上,则需要使用maxAge,并给出一个以秒为单位的时间。将最大时效设为0则是命令浏览器删除该cookie。

(5) 删除cookie时,path必须一致,否则不会删除

2.5 案例一 Cookies记录时间

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//设置到达客户端的输出数据的编码格式
		response.setContentType("text/html;charset=utf-8");
		//获得界面的Cookies
		Cookie[] cookies = request.getCookies();
		PrintWriter writer = response.getWriter();
		for(Cookie co:cookies){
			if(co.getName().equals("lastTime")){
				String value = co.getValue();
				writer.write("上次访问时间是:"+value);
			}
		}
		Date date = new Date();
		Cookie cookie=new Cookie("lastTime",date.toString());
     Cookie.setPath(“/”);
     Cookie.setMaxAge(1000*30);
		response.addCookie(cookie);
}

如上代码所示,我们先获取上次页面中的cookies,如果没有的话生成一个cookies返回到页面,下一次就可以获取到cookies到页面进行输出。

如上图所示是上面的代码,返回到页面之后形成的cookies的样例,一个cookie是由

Name cookies的名称。

Value cookies的值。

Domain  cookies所属的主机域。

Path cookies的路径,下一个再请求同样的地址的时候,就会带上对应的cookie。当前访问路径如果是以cookies path开头的就带上cookies,否则就不带cookies,可以在服务端返回cookie的时候就手动给cookie设置路径,这样的话等到cookie访问设置的路径的时候,它就会自动的带上cookie了。

cookie.setPath("/");

Expires/max-age cookie的最大存活时间。setMaxAge() 正数cookie保存指定时间,负数cookie永久保存,直到关闭当前会话,0表示立即删除cookie。

2.7 案列二 cookie浏览记录

实现思路:把浏览的列表的id的集合,用一个cookie的字段做记录

每浏览一个记录往cookie的id集合中添加一个,当大于制定值的时候

把cookie中的第一个删掉,添加当前值,如果集合中包含当前值,先删除

当前浏览的值,再重复上面的判断。

Size cookies 的指定大小。

2.7.1 列表

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		Map allCollege = DBUtils.getAllCollege();
		Set entrySet = allCollege.entrySet();
		Iterator it = entrySet.iterator();
		StringBuffer buffer=new StringBuffer();
		buffer.append("大学列表如下所示:");
		while(it.hasNext()){
	        Map.Entry<Integer, String> next = (Entry<Integer, String>) it.next();
	        Integer key =(Integer) next.getKey();
			String name = next.getValue();
			buffer.append("<br>");
			buffer.append("<a href="+request.getContextPath()+"/ServletDetails?key="+key+">"+name+"</a>");
			buffer.append("<br>");
		}
		buffer.append("最近浏览的历史记录:<br>");
		Cookie[] cookies = request.getCookies();
	    for(int i=0; cookies!=null&&i<cookies.length;i++){
	    	if(cookies[i].getName().equals("history")){
	    		String value = cookies[i].getValue();
	    		String[] split = value.split("-");
	    		for(String str:split){
	    			String byId = DBUtils.getById(Integer.valueOf(str));
	    			buffer.append("<br>");
	    			buffer.append("<a href="+request.getContextPath()+"/ServletDetails?key="+str+">"+byId+"</a>");
	    			buffer.append("<br>");
	    		}
	    	}
	    }
		String string = buffer.toString();
		PrintWriter writer = response.getWriter();
		writer.write(string);
		writer.close();
	}

2.7.2详细

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		String key = request.getParameter("key");
		String byId = DBUtils.getById(Integer.valueOf(key));
	    Cookie[] cookies = request.getCookies();
	    String history=null;
	    for(int i=0;cookies!=null&&i<cookies.length;i++){
	    	if(cookies[i].getName().equals("history")){
	    		history=cookies[i].getValue();
	    	}
	    }
	    Cookie cookies2 = getCookies(key, history);
	    response.addCookie(cookies2);
		ServletOutputStream outputStream = response.getOutputStream();
		byte[] bytes = byId.getBytes();
		outputStream.write(bytes);
		outputStream.close();
	}

	private Cookie getCookies(String key, String history) {
		if(null!=history){
		   String[] split = history.split("-");
		   LinkedList<String> lik=new LinkedList<String>(Arrays.asList(split));
		   if(lik.contains(key)) lik.remove(key);
		   if(lik.size()==3) lik.removeFirst();
		   lik.addLast(key);
		   StringBuffer buf=new StringBuffer();
		   for(int i=0;i<lik.size();i++){
			   if(i>0){
				   buf.append("-");
			   }
			   buf.append(lik.get(i));
		   }
		   return new Cookie("history", buf.toString());
		}
		return new Cookie("history", key);
	}

2.7.3 DB

public class DBUtils {
	private static Map map=new HashMap();
    static{
      map.put(1, "中国人民大学");
      map.put(2, "上海交通大学");
      map.put(3, "华东师范大学");
      map.put(4, "北京理工大学");
    }
    public static String getById(int id){
    	 return (String) map.get(id);
    }
    public static Map getAllCollege(){
    	return map;
    }
}

2.7.4 结果

2.6 删除cookie

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		Cookie cookie=new Cookie("lastTime","");
		cookie.setPath("/");
		cookie.setMaxAge(0);
		response.addCookie(cookie);
}

如上图所示第一次访问的时候还可以看到如上图所示的cookie的返回值,并可以清晰的看到cookie的相关信息,当我点击clear执行上面的代码的时候

如上图所示cookie已经被清理了,此时我们再访问,原绘画的路径

发现首次访问的时候,已经拿不到cookie中的信息了,原因是我点clear的时候执行相应的代码删除掉了。

三 什么是session

Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的HttpSession对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其它web资源时,其它web资源再从用户各自的session中取出数据为用户服务。

如上图所示是一个session的放映,如上图所示客户端每开启一个浏览器默认对服务器产生了一个唯一的绘话,直到客户端关闭浏览器会话才算结束。如上图服务器为客户端的每一个绘画开启了一个存储介质。也就是我们所说的session技术。简单的说每一个打开一个浏览器就相当于创建了一个session。

3.1 session传值原理

如上图所示的session原理图,当浏览器第一次放问服务器的时候,浏览器是不待有jsessionid的cookies的所以,在调用request.getSession()的时候,实际上是先创建了一个session,然后再把session的id返回到客户端做记录,当客户端浏览器再次访问服务器的时候,将通过浏览器中cookies中时候存在session再做是否创建session的判断,所以很多用户,打开很多浏览器,各自的数据存储在了各自的session里面,并不会错乱。

3.2 session API

void setAttribute(String name,Object value); 向session中填值

Object getAttribute(String name); 向session中取值

void removeAttribute(String name); 删除session中的值

HttpSession.getId():获取session对应的id值

setMaxInactiveInterval(int interval) 设置session的存活时间

invalidate() 使此会话无效

3.3 getSession() 原理

HttpSession request.getSession():内部执行原理

1、获取名称为JSESSIONID的cookie的值。

2、没有这样的cookie,创建一个新的HttpSession对象,分配一个唯一的SessionID,并且向客户端写了一个名字为JSESSIONID=sessionID的cookie

3、有这样的Cookie,获取cookie的值(即HttpSession对象的值),从服务器的内存中根据ID找那个HttpSession对象:

找到了:取出继续为你服务。

找不到:从2开始。

HttpSession request.getSession(boolean create):

参数:

true:和getSession()功能一样。

false:根据客户端JSESSIONID的cookie的值,找对应的HttpSession对象,找不到返回null(不会创建新的,只是查询)。

3.4案例一session购物车

3.4.1列出所有的物品

public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
		request.getSession();
		out.print("本网站有以下好书:<br/>");
		Map<String, Book> books = DBUtil.findAllBooks();
		for (Map.Entry<String, Book> book : books.entrySet()) {
			String url = request.getContextPath()+"/servlet/addCart?id="+book.getKey();
		out.print("<a href='"+response.encodeURL(url)+"' >"+book.getValue().getName()+"</a><br/>");
		}
		String url2 = request.getContextPath()+"/servlet/showCart";
		out.print("<a href='"+response.encodeURL(url2)+"'>查看购物车</a>");
	}

3.4.2添加购物车

public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
		//根据id得到书
		String id = request.getParameter("id");
		Book book = DBUtil.findBookById(id);
		//得到session对象
		 HttpSession session = request.getSession();
		//从session中取出list(购物车)
		List<Book> list = (List<Book>)session.getAttribute("cart");
		if(list==null){
			list = new ArrayList<Book>();
		}
		list.add(book);
		session.setAttribute("cart", list);//把list放回到session域中
		out.print("购买成功!");
		String url = request.getContextPath()+"/servlet/showAllBooksServlet";
	}

3.4.3展示购物车

public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
		out.print("购物车有以下商品:<br/>");
		 HttpSession session = request.getSession();
		//得到session对象
		List<Book> books = (List<Book>)session.getAttribute("cart");
		if(books==null){
			out.print("你还什么都没买呢");
			response.setHeader("refresh", "2;url="+request.getContextPath()+"/servlet/showAllBooksServlet");		
                        //response.sendRedirect(request.getContextPath()+"/servlet/showAllBooksServlet");
			return;
		}
		for (Book book : books) {
			out.write(book.getName()+"<br/>");
		}
		//session.setMaxInactiveInterval(10);
	}

&lt;think&gt;好的,我现在需要帮助用户解决关于使用Python的requests库中的session提取cookies的问题。首先,用户之前遇到了TooManyRedirects的错误,可能是在处理认证或会话时出现了问题。现在用户询问如何提取cookies,这可能与之前的重定向问题有关联。 首先,我要回顾用户的历史对话。之前的错误提示显示,用户在使用session.post时触发了超过30次的重定向。我的回复中提到了可能需要检查cookies是否正确携带,所以用户现在可能想确认如何正确提取和管理cookies,以避免重定向循环。 接下来,我需要思考用户可能的场景。用户可能在编写一个自动化脚本,用于与某个网站交互,比如登录后提交表单。由于重定向问题,用户需要确保session正确保存了cookies,以便后续请求能够维持会话状态。用户可能不太清楚如何从session中提取cookies,或者在提取后如何正确使用它们。 用户的需求是什么?表面上是如何提取cookies,但深层需求可能是确保会话状态正确,避免因cookies问题导致的重定向或认证失败。用户可能遇到的情况包括:登录后cookies未正确保存,后续请求没有携带必要的cookies,或者需要跨session使用cookies。 接下来,我需要组织回答的结构。首先介绍基本方法,展示如何从session中提取cookies,然后说明如何手动设置cookies到新的请求中。接着,提供验证步骤,确保cookies正确应用。此外,要加入高级技巧,比如使用钩子函数或持久化存储,帮助用户更灵活地处理cookies。最后,安全注意事项也很重要,提醒用户保护敏感信息。 我需要确保回答清晰,步骤明确,并给出代码示例。例如,使用session.cookies.get_dict()来获取cookies字典,或者直接访问特定的cookie。同时,需要强调在跨session使用时正确应用cookies的方法,比如在headers中添加Cookie头,或者使用RequestsCookieJar对象。 还要考虑用户可能的错误,比如没有正确处理cookies的更新。例如,某些网站可能在重定向时更新cookies,用户需要确保每次请求后都更新cookies存储。此外,用户可能没有注意到某些cookies是HttpOnly,无法通过脚本访问,这可能需要其他方法处理。 需要提醒用户验证cookies是否正确,可以通过打印输出或调试工具检查。同时,高级技巧中的流量抓包和钩子函数可以帮助用户更深入地调试问题。最后,安全部分要强调不要泄露敏感cookies,避免安全风险。 总结,用户需要的是从session中提取cookies的具体方法,以及如何正确使用这些cookies来维持会话状态,解决之前的重定向问题。回答需要覆盖基本提取、手动应用、验证步骤、高级技巧和安全提示,确保用户能够全面理解和应用。&lt;/think&gt;以下是关于在Python `requests`库中从`Session`对象提取和管理Cookies的详细指南: --- ### **1. 基础Cookie提取方法** #### **1.1 查看Session中所有Cookies** ```python import requests session = requests.Session() response = session.get(&quot;https://example.com/login&quot;) # 方法1:获取Cookies字典 cookies_dict = session.cookies.get_dict() print(&quot;当前Cookies字典:&quot;, cookies_dict) # 方法2:获取RequestsCookieJar对象(完整属性) cookies_jar = session.cookies print(&quot;完整Cookie对象:&quot;, cookies_jar) # 方法3:遍历单个Cookie for cookie in cookies_jar: print(f&quot;名称: {cookie.name}, : {cookie.value}, 过期时间: {cookie.expires}&quot;) ``` #### **1.2 提取指定Cookie** ```python # 获取特定Cookie(Key不存在返回None) auth_token = session.cookies.get(&quot;session_id&quot;) print(&quot;关键认证令牌:&quot;, auth_token) ``` --- ### **2. 手动应用Cookies** #### **2.1 跨Session复用Cookies** ```python # 创建新Session并注入之前获取的Cookies new_session = requests.Session() # 方法A:通过字典设置 new_session.cookies.update(cookies_dict) # 方法B:直接操作CookieJar for cookie in cookies_jar: new_session.cookies.set_cookie(cookie) ``` #### **2.2 单次请求携带Cookies** ```python # 通过headers传递(原始字符串格式) headers = { &quot;Cookie&quot;: f&quot;session_id={auth_token}; user_lang=zh-CN&quot; } # 通过cookies参数传递(推荐字典格式) requests.get(&quot;https://example.com/data&quot;, cookies=cookies_dict) ``` --- ### **3. 关键验证步骤** #### **3.1 实时监控Cookies变化** ```python # 定义调试钩子函数 def cookie_monitor(response, *args, **kwargs): print(&quot;\n[COOKIE监控]&quot;) print(&quot;请求URL:&quot;, response.request.url) print(&quot;新Cookies:&quot;, response.cookies.get_dict()) # 绑定到Session session = requests.Session() session.hooks[&#39;response&#39;].append(cookie_monitor) # 触发请求时自动输出变化 session.get(&quot;https://example.com&quot;) ``` #### **3.2 验证Cookie有效性** ```python # 检查是否包含必要凭证 required_cookies = [&quot;session_id&quot;, &quot;csrf_token&quot;] missing = [c for c in required_cookies if c not in session.cookies] if missing: raise Exception(f&quot;缺少关键Cookie: {missing}&quot;) # 验证Cookie作用域 target_domain = &quot;example.com&quot; if not any(c.domain == target_domain for c in session.cookies): raise Exception(&quot;Cookie作用域不匹配&quot;) ``` --- ### **4. 高级技巧** #### **4.1 持久化存储Cookies** ```python import json import http.cookiejar # 保存到文件(Mozilla格式) session.cookies.save(ignore_discard=True, ignore_expires=True) # 从文件加载 session.cookies = http.cookiejar.MozillaCookieJar() session.cookies.load(&quot;cookies.txt&quot;, ignore_discard=True, ignore_expires=True) # JSON序列化(适合临时存储) with open(&quot;cookies.json&quot;, &quot;w&quot;) as f: json.dump(requests.utils.dict_from_cookiejar(session.cookies), f) ``` #### **4.2 处理动态Cookie更新** ```python # 强制更新Cookie(应对服务端刷新) redirect_response = session.post(&quot;https://example.com/update&quot;) session.cookies.update(redirect_response.cookies) ``` --- ### **5. 安全注意事项** 1. **敏感信息保护**: - 避免日志中记录`Set-Cookie`头 - 使用`cookie.secure`属性验证是否仅通过HTTPS传输 2. **作用域限制**: ```python # 检查Cookie是否允许跨域 if any(not c.restricted for c in session.cookies): print(&quot;警告:存在非安全作用域Cookie&quot;) ``` 3. **过期管理**: ```python # 自动清理过期Cookie session.cookies.clear_expired_cookies() ``` --- ### **典型问题排查** | 现象 | 解决方案 | |-------|-------| | 登录后Cookie未保存 | 检查响应状态码是否为200/302,确认服务端实际返回了Cookie | | Cookie跨域失效 | 验证`domain`和`path`属性是否匹配目标URL | | 部分Cookie丢失 | 使用`session.cookies = requests.cookies.merge_cookies()`合并新旧 | --- 通过以上方法,您可以精确控制Cookie的提取和应用过程。如果遇到特定网站的特殊Cookie机制(如`HttpOnly`标志或加密Cookie),建议结合浏览器开发者工具进行网络请求对比分析。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值