问道session_id或sessionid_v1.0.0

本文深入探讨JSessionID的工作原理及应用场景,包括其在登录过程中的作用、如何通过浏览器获取及跟踪,以及在不同请求间的变化情况。同时,还介绍了禁用cookie时的URL重写策略。

v1.0.0
token、jwt、oauth2标准,统统都玩腻了?不是。那为什么突然调研session?因为也很重要呀。

开始

登录原理
git clone https://gitee.com/lcg0124/bootdo

sql
启动
登录成功

jsessionid

使用Chrome浏览器,按F12,随便点一个接口,观察XHR,找到刚才访问的接口,找到请求头,找到cookie,记住cookie里的jsessionid

Cookie: csrftoken=v4a4CLBKD7CxSsPf66qmph2e2MPU6xmpPZ142dBg8Dh4q0pa0ynOeA9wwmHAtZOW;
JSESSIONID=e3baf1ce-3d08-4601-8f90-444b984638c1;
NG_TRANSLATE_LANG_KEY=%22en%22

再访问另一个接口,继续观察jsessionid:

Cookie: csrftoken=v4a4CLBKD7CxSsPf66qmph2e2MPU6xmpPZ142dBg8Dh4q0pa0ynOeA9wwmHAtZOW; 
JSESSIONID=e3baf1ce-3d08-4601-8f90-444b984638c1; 
NG_TRANSLATE_LANG_KEY=%22en%22

是一样的。
退出
再登录
再调接口,
访问一个裸奔的接口,也就是不需要授权就能访问的接口,观察发现没有jsessionid了:

Cookie: csrftoken=v4a4CLBKD7CxSsPf66qmph2e2MPU6xmpPZ142dBg8Dh4q0pa0ynOeA9wwmHAtZOW; 
NG_TRANSLATE_LANG_KEY=%22en%22

裸奔配置:

ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        shiroFilterFactoryBean.setLoginUrl("/login");
        shiroFilterFactoryBean.setSuccessUrl("/index");
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/blog", "anon");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;

到登录页面,查看验证码接口,是img的,观察jsessionid:

Cookie: csrftoken=v4a4CLBKD7CxSsPf66qmph2e2MPU6xmpPZ142dBg8Dh4q0pa0ynOeA9wwmHAtZOW; 
NG_TRANSLATE_LANG_KEY=%22en%22; 
JSESSIONID=51918ca9-0872-4373-8dc9-e871a11da7f8

与上文的id不一样了,再观察id的结构,——应该是个uuid。
说明uuid有被删除的可能,多次刷新登录页面,发现该uuid没有变,那么触发删除大概是在logout的时候了。
从英文单词可以看出它叫会话(session),那么关闭当前页面,重新打开,看下id会变不,发现没变,那么关闭浏览器再打开试试,注意,用同一个浏览器,还是查看图片验证码接口,发现id不见了:
在这里插入图片描述
是不是还没设置到cookie?于是观察响应头,果然:
在这里插入图片描述
哈?原来这个id是后台返回的呀。当然了,session嘛,当然是服务端session呀。
在任意请求添加这句代码:

System.out.println(String.format("jsessionid == %s", session.getId()));

out:
在这里插入图片描述
打开一个新tab页(id不变),或者换一个浏览器(不一样了)观察jsessionid。
登录成功,关闭浏览器,重新打开浏览器,直接访问首页,是不是登录失效了?为什么?既然叫session嘛,会话,会话取消了,就中断退出了呀。当然,这里还与过期时间有关,如果有印象的话,你应该记得过期日期是1970.
服务端是如何取得cookie里的jsessionid的?tomcat服务端可以操作cookie,并从中获得id,前提是cookie里有传,这一点也类似后来发展起来的无状态token访问。
禁用了cookie咋办?url重写,将jsessionid写到url。

headers = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)" " Chrome/116.0.5845.97 Safari/537.36 Core/1.116.537.400 QQBrowser/19.4.6561.400" } cookies=('x-web-secsdk-uid=6caa94ab-afcf-4fd4-afbb-8bc8452fe9be; Hm_lvt_2667d29c8e792e6fa9182c20a3013175=1753504097;' ' HMACCOUNT=3521586B2CBB60FD; s_v_web_id=verify_mdjr2cq7_0Awh10ms_xmxg_4RxP_ACcS_6L26t2CAuVN7;' ' csrf_session_id=42d699e530338ed5c27470544ca7f4d1; novel_web_id=7531242700978275891; gfkadpd=2503,36144;' ' serial_uuid=7531242700978275891; serial_webid=7531242700978275891; passport_csrf_token=456e18769bc01214ea4b162181d52c57; ' 'passport_csrf_token_default=456e18769bc01214ea4b162181d52c57;' ' passport_mfa_token=Ci%2BRmTcFLTjXAtuCAzxfHTr5xzh%2FeJAq9pCuk%2FlI65%2BK0XFl43i3nA5U27bvl3phfBpKCjwAAAAAAAAAAAAAT0cRRwFSohWydrXo5%2B%2FUfenqaq2QfGYbBk2u8N3i7t0vf%2B%2Bba1Iwc%2FGAe5KLLYMdq50Q0eD3DRj2sdFsIAIiAQMlxlhx; d_ticket=40365a26b04ae00fd40c24bf84c595e569134; odin_tt=64775b0e5c16e19ea1dcfc0bc2803975e7fe1fa238f7079fad44eb74d422a92b13922f254dfe242c1a10e398110f4a81; n_mh=Q_Sm8BYjtPoAOYv_SaH5P9NQDPqDZ7xoQRgI2GvcfEw; sid_guard=4b4ce70ae45606de9ccf894f86577bf9%7C1753504126%7C5184000%7CWed%2C+24-Sep-2025+04%3A28%3A46+GMT; uid_tt=9828be745c0647d8029cb6544523a987; uid_tt_ss=9828be745c0647d8029cb6544523a987; sid_tt=4b4ce70ae45606de9ccf894f86577bf9; sessionid=4b4ce70ae45606de9ccf894f86577bf9; sessionid_ss=4b4ce70ae45606de9ccf894f86577bf9; session_tlb_tag=sttt%7C11%7CS0znCuRWBt6cz4lPhld7-f________-7F1LcICKBvVj_qj8slUjAFUXFSpOSZ6rZJkWDYtmHBVs%3D; is_staff_user=false; sid_ucp_v1=1.0.0-KGM1OTZmODRmM2NhMjEyNDE4ZjA1YzIzZjhlZDRjOWU0Yjg3ZWY4MTkKHQj_svrjugIQ_rKRxAYYxxMgDDC8gbzSBTgCQO8HGgJobCIgNGI0Y2U3MGFlNDU2MDZkZTljY2Y4OTRmODY1NzdiZjk; ssid_ucp_v1=1.0.0-KGM1OTZmODRmM2NhMjEyNDE4ZjA1YzIzZjhlZDRjOWU0Yjg3ZWY4MTkKHQj_svrjugIQ_rKRxAYYxxMgDDC8gbzSBTgCQO8HGgJobCIgNGI0Y2U3MGFlNDU2MDZkZTljY2Y4OTRmODY1NzdiZjk; Hm_lpvt_2667d29c8e792e6fa9182c20a3013175=1753505316; ttwid=1%7CYbkOCAUHGSmJvwiQZl87vIuNuIeLtgcPuvxpcdV-nME%7C1753505317%7Ca23a7bc2cffe611918008995cea7fdf595616ea6cfe9a04215858502f0d6a522') cookies_jar=requests.cookies.RequestsCookieJar() for cookie in cookies.split(';'): key,value=cookie.split('=',1) cookies_jar.set(key,value)
08-07
完整的接口代码如下: import json import os import sys from time import time import uvicorn from aipaas.logger_factory import logger from fastapi import Request, FastAPI from fastapi.responses import StreamingResponse from langchain_core.messages import HumanMessage from infrastructure.auth_fastapi import SoaAuth from infrastructure.langfuse_telemetery.trace_langgraph import create_langfuse_callback from scm_agent.src.application.roles.order.supply_manager_assistant_graph.main_graph.graph import \ get_supply_manager_assistant_main_graph from scm_agent.src.common.agent_name import AgentName from scm_agent.src.common.constants import Status from scm_agent.src.infrastructures.agent_config_download.config_download import dowload_agent_config_langgraph from scm_agent.src.infrastructures.agent_config_read.read_yaml_config import read_project_config from scm_agent.src.infrastructures.agent_state.agent_state_helper import get_redis_key from scm_agent.src.infrastructures.app_postprocess.output_process import str_to_output_json from scm_agent.src.infrastructures.app_postprocess.output_process import str_to_stream_output_langgraph from scm_agent.src.infrastructures.memory.postgre_checkpointer.postgre_checkpointer import FrameworkAdapter from scm_agent.src.infrastructures.read_config import app_config from scm_agent.src.interface.input_output_parameters import SupplyManagerAssistantChatInput, ConfigUpdateInput, \ ConfigUpdateOutput os.environ['NO_PROXY'] = '127.0.0.1,localhost' fastapi_app = FastAPI(lifespan=FrameworkAdapter.lifespan_wrapper) env = os.environ.get("env") soa = SoaAuth(env_type=env, skip_soa_auth=False, only_check_token=True) agent_name = AgentName.SupplyManagerAssistantLangGraph project_config = {} common_prompt_config = {} def preload_agent_config(name): """ 预加载agent配置 Args: name: 助手/技能名称,app_config中配置 """ global project_config global common_prompt_config dowload_agent_config_langgraph(name) # 读取项目配置文件 project_config = read_project_config(agent_name, f"{agent_name}.yaml").get(env) # 读取公共Prompt配置文件 common_prompt_config = read_project_config("common", "prompt_config.yaml") if 'PYCHARM_HOSTED' in os.environ or 'PYCHARM_DEBUG_PROCESS' in os.environ: logger.info("debug模式请在此打断点") # raise Exception("debug模式请在此打断点,注释此行即可") preload_agent_config(agent_name) async def generator(graph, supply_manager_assistant_chat_input, initial_state, config): yield str_to_stream_output_langgraph('<think>') yield str_to_stream_output_langgraph('**问题**') question = supply_manager_assistant_chat_input.question.strip() yield str_to_stream_output_langgraph('\n' + question) async for chunk in graph.astream( input=initial_state, stream_mode="custom", config=config, subgraphs=True ): yield str_to_stream_output_langgraph(chunk[1]) @fastapi_app.post('/roles/supply_manager_assistant_chat_langgraph') @soa.required async def supply_manager_assistant_chat(request: Request, supply_manager_assistant_chat_input: SupplyManagerAssistantChatInput): strategy = request.app.state.presist_param["checkpointer"] thread_id = get_redis_key(supply_manager_assistant_chat_input) user_id = supply_manager_assistant_chat_input.user_id session_id = supply_manager_assistant_chat_input.session_id langfuse_callback = create_langfuse_callback( user_id=user_id, session_id=session_id, trace_name=AgentName.SupplyManagerAssistantLangGraph ) config = { "configurable": {"thread_id": thread_id}, "metadata": { "user_id": user_id, "project_config": project_config, "common_prompt_config": common_prompt_config, "ctx_params": supply_manager_assistant_chat_input.ctxParams }, "callbacks": [langfuse_callback], } try: async with strategy as checkpointer: graph = get_supply_manager_assistant_main_graph(checkpointer) initial_state = {"messages": [HumanMessage(content=supply_manager_assistant_chat_input.question.strip())]} return StreamingResponse( generator(graph, supply_manager_assistant_chat_input, initial_state, config), media_type="text/event-stream", headers={"Cache-Control": "no-cache", "Connection": "keep-alive"} ) except Exception as e: logger.error(f"[supply_manager_assistant_chat] 执行失败: {e}", exc_info=True) return str_to_output_json(f'处理异常,异常原因:{e}') @fastapi_app.post('/config_update') @soa.required async def config_update(request: Request, config_update_input: ConfigUpdateInput): start_time = time() config_update_output = ConfigUpdateOutput() try: preload_agent_config(config_update_input.agent_name) config_update_output.status = Status.SUCCESS except Exception as e: config_update_output.error_message = "[SCM-Agent] Update config error." # 耗时统计 config_update_output.elapsed_time = str(time() - start_time) return config_update_output.to_dict() @fastapi_app.get('/health') @soa.required async def health(request: Request, ): return json.dumps({"success": True}, ensure_ascii=False) if __name__ == '__main__': uvicorn.run("supply_manager_assistant_app_langgraph:fastapi_app", host=app_config.get('host', '0.0.0.0'), # port=app_config.get('port', 8080), loop="asyncio", port=8080) # workers=app_config.get('workers', 4)) 请你在这个基础上进行适配,最后完整输出
最新发布
09-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值