Cookie值最好不要为中文

本文描述了在SpringBoot项目中使用Undertow作为内嵌Servlet容器时,设置包含中文字符的Cookie值会导致异常的问题。该问题在使用Tomcat时不会出现。

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

今天遇到一个问题,Spring Boot 项目,Boot版本1.5.9.RELEASE,内置tomcat版本为8.5.23,内置undertow.version为1.4.21.Final。

  • 使用Tomcat时,可以添加中文值的Cookie

  • 使用Undertow时会报错
 1 Caused by: java.lang.IllegalArgumentException: UT000173: An invalid control character [31616] was present in the cookie value or attribute
 2     at io.undertow.util.LegacyCookieSupport.isHttpSeparator(LegacyCookieSupport.java:149) ~[undertow-core-1.4.21.Final.jar:1.4.21.Final]
 3     at io.undertow.util.LegacyCookieSupport.isHttpToken(LegacyCookieSupport.java:170) ~[undertow-core-1.4.21.Final.jar:1.4.21.Final]
 4     at io.undertow.util.LegacyCookieSupport.adjustedCookieVersion(LegacyCookieSupport.java:255) ~[undertow-core-1.4.21.Final.jar:1.4.21.Final]
 5     at io.undertow.server.Connectors.getCookieString(Connectors.java:154) ~[undertow-core-1.4.21.Final.jar:1.4.21.Final]
 6     at io.undertow.server.Connectors.flattenCookies(Connectors.java:99) ~[undertow-core-1.4.21.Final.jar:1.4.21.Final]
 7     at io.undertow.server.protocol.http.HttpResponseConduit.processWrite(HttpResponseConduit.java:161) ~[undertow-core-1.4.21.Final.jar:1.4.21.Final]
 8     at io.undertow.server.protocol.http.HttpResponseConduit.write(HttpResponseConduit.java:596) ~[undertow-core-1.4.21.Final.jar:1.4.21.Final]
 9     at io.undertow.conduits.AbstractFixedLengthStreamSinkConduit.write(AbstractFixedLengthStreamSinkConduit.java:106) ~[undertow-core-1.4.21.Final.jar:1.4.21.Final]
10     at org.xnio.conduits.ConduitStreamSinkChannel.write(ConduitStreamSinkChannel.java:150) ~[xnio-api-3.3.8.Final.jar:3.3.8.Final]
11     at io.undertow.channels.DetachableStreamSinkChannel.write(DetachableStreamSinkChannel.java:240) ~[undertow-core-1.4.21.Final.jar:1.4.21.Final]
12     at io.undertow.server.HttpServerExchange$WriteDispatchChannel.write(HttpServerExchange.java:2094) ~[undertow-core-1.4.21.Final.jar:1.4.21.Final]
13     at io.undertow.servlet.spec.ServletOutputStreamImpl.writeBufferBlocking(ServletOutputStreamImpl.java:573) ~[undertow-servlet-1.4.21.Final.jar:1.4.21.Final]
14     at io.undertow.servlet.spec.ServletOutputStreamImpl.flushInternal(ServletOutputStreamImpl.java:488) ~[undertow-servlet-1.4.21.Final.jar:1.4.21.Final]
15     at io.undertow.servlet.spec.ServletOutputStreamImpl.flush(ServletOutputStreamImpl.java:475) ~[undertow-servlet-1.4.21.Final.jar:1.4.21.Final]
16     at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:297) ~[?:1.8.0_131]
17     at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141) ~[?:1.8.0_131]
18     at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229) ~[?:1.8.0_131]
19     at org.springframework.util.StreamUtils.copy(StreamUtils.java:119) ~[spring-core-4.3.13.RELEASE.jar:4.3.13.RELEASE]
20     at org.springframework.http.converter.StringHttpMessageConverter.writeInternal(StringHttpMessageConverter.java:106) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
21     at org.springframework.http.converter.StringHttpMessageConverter.writeInternal(StringHttpMessageConverter.java:41) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
22     at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:227) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
23     at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:247) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
24     at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:174) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
25     at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:81) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
26     at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:113) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
27     at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
28     at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
29     at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
30     at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
31     at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
32     at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.13.RELEASE.jar:4.3.13.RELEASE]
33     ... 59 more

 

转载于:https://www.cnblogs.com/520130phx/p/10656540.html

<think>我们正在讨论如何在Flask中设置中文Cookie。注意,根据RFC标准,Cookie通常是URL编码的,并且不支持非ASCII字符。但是我们可以通过编码(如UTF-8)然后进行URL编码来解决。在Flask中,我们可以使用`set_cookie`方法。由于中文字符需要编码,我们可以使用`urllib.parse.quote`进行URL编码,读取时再使用`urllib.parse.unquote`解码。同时,注意设置max_age或expires来设定有效期,以及path等参数。下面是一个设置中文Cookie的示例:步骤:1.导入Flask和make_response,以及urllib.parse.quote。2.创建一个路由,在响应中设置Cookie。3.使用quote对中文字符串进行编码。4.在响应中设置Cookie,并设置其他可选参数(如max_age等)。5.读取Cookie时,使用unquote进行解码。另外,根据引用[2]:如果设置了过期时间,则Cookie会被保存在硬盘上,否则为临时Cookie(关闭浏览器即失效)。下面给出示例代码:</think> 在 Flask 中设置中文 Cookie 需要特别注意编码处理,因为 Cookie 标准要求使用 URL 安全的 ASCII 字符。以下是完整解决方案: ### Flask 设置中文 Cookie 的两种方法 #### 方法 1:手动 URL 编码(推荐) ```python from flask import Flask, make_response from urllib.parse import quote, unquote app = Flask(__name__) @app.route('/set_cookie') def set_cookie(): resp = make_response("已设置中文Cookie") # 中文内容 → URL编码 chinese_value = "你好世界" encoded_value = quote(chinese_value) resp.set_cookie( 'chinese_cookie', value=encoded_value, max_age=3600, # 1小时有效期 path='/', secure=True, httponly=True ) return resp @app.route('/get_cookie') def get_cookie(): # 获取并解码 encoded_value = request.cookies.get('chinese_cookie') decoded_value = unquote(encoded_value) if encoded_value else None return f"Cookie: {decoded_value}" ``` #### 方法 2:JSON + Base64(处理复杂数据结构) ```python import base64 import json @app.route('/set_complex_cookie') def set_complex_cookie(): resp = make_response("已设置中文Cookie") data = {"名字": "张三", "地址": "北京市朝阳区", "产品": ["手机", "电脑"]} # 序列化为JSON → Base64编码 json_str = json.dumps(data, ensure_ascii=False) encoded_value = base64.b64encode(json_str.encode('utf-8')).decode('ascii') resp.set_cookie('complex_cookie', encoded_value) return resp ``` ### 关键说明: 1. **编码必要性**:直接使用中文会违反 RFC 6265 规范,可能导致乱码或浏览器拒绝接受[^1] 2. **有效期控制**: - `max_age=秒数` 设置相对过期时间 - `expires=datetime对象` 设置绝对过期时间 - 未设置则默认为会话 Cookie(关闭浏览器失效)[^2] 3. **安全设置**: - `secure=True` 仅通过 HTTPS 传输 - `httponly=True` 阻止 JavaScript 访问 - `samesite='Lax'` 防止 CSRF 攻击 ### 注意事项: 1. URL 编码后的长度会显著增加,需确保不超过浏览器限制(通常 4KB/domain) 2. 处理中文字符时始终明确指定 UTF-8 编码 3. 对于敏感信息应考虑客户端加密处理 ````
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值