欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Cookie:java.lang.IllegalArgumentException: An invalid character [32] was present in the Cookie value

程序员文章站 2022-05-15 18:28:07
...

使用servlet写一个案例:显示用户的上次访问时间分析
爆出一下的错误:
java.lang.IllegalArgumentException: An invalid character [32] was present in the Cookie value
控制台输出如下:

严重: Servlet.service() for servlet [com.zhiyou.servlet.lastaccesstime.LastAccessTimeServlet] in context with path [/stu04] threw exception
java.lang.IllegalArgumentException: An invalid character [32] was present in the Cookie value
    at org.apache.tomcat.util.http.Rfc6265CookieProcessor.validateCookieValue(Rfc6265CookieProcessor.java:182)
    at org.apache.tomcat.util.http.Rfc6265CookieProcessor.generateHeader(Rfc6265CookieProcessor.java:115)
    at org.apache.catalina.connector.Response.generateCookieString(Response.java:976)
    at org.apache.catalina.connector.Response.addCookie(Response.java:928)
    at org.apache.catalina.connector.ResponseFacade.addCookie(ResponseFacade.java:385)
    at com.zhiyou.servlet.lastaccesstime.LastAccessTimeServlet.doGet(LastAccessTimeServlet.java:31)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:668)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:770)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source)

了解到 An invalid character [32] was present in the Cookie value 中32对应的编码是空格,Stack Overflow上的回答:This is due to Tomcat’s cookie processing being changed to a RFC 6265 compliant implementation by default in 8.5, which does not allow space (character 32), among others.

tomcat版本是9.0,cookie存的值确实有空格,改用编码后再存入cookie,可避免出现空格。

修改后的代码如下:

import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/lastAccessTime")
public class LastAccessTimeServlet extends HttpServlet {
    /** 
    * serialVersionUID:
    */
    private static final long serialVersionUID = -3666204851005119865L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        //获得当前时间
        Date date = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        String currentTime = format.format(date);

        //1、创建Cookie 记录当前的最新的访问时间
//      Cookie cookie = new Cookie("lastAccessTime",currentTime);//报错地方
        //deBug:格式化后的date值,通过编码存入cookie
        Cookie cookie = new Cookie("lastAccessTime",URLEncoder.encode(currentTime,"UTF-8"));
        cookie.setMaxAge(60*10*500);
        response.addCookie(cookie);

        //2、获得客户端携带cookie ---- lastAccessTime
        String lastAccessTime = null;
        Cookie[] cookies = request.getCookies();
        if(cookies!=null){
            for(Cookie coo : cookies){
                if("lastAccessTime".equals(coo.getName())){
                    lastAccessTime = coo.getValue();
                }
            }
        }
        response.setContentType("text/html;charset=UTF-8");
        if(lastAccessTime==null){
            response.getWriter().write("您是第一次访问");
        }else{
            //
            response.getWriter().write("您上次的访问的时间是:"+lastAccessTime);
            //deBug:cookie取出的值,通过解码显示到页面上
            response.getWriter().write("您上次的访问的时间是:"+URLDecoder.decode(lastAccessTime,"UTF-8"));
        }
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

归纳总结

关于使用Cookie的一些注意事项:

1. Cookie的兼容性问题

Cookie的格式有2个不同的版本,第一个版本,我们称为Cookie Version 0,是最初由Netscape公司制定的,也被几乎所有的浏览器支持。而较新的版本,Cookie Version 1,则是根据RFC 2109文档制定的。为了确保兼容性,JAVA规定,前面所提到的涉及Cookie的操作都是针对旧版本的Cookie进行的。而新版本的Cookie目前还不被Javax.servlet.http.Cookie包所支持。

2. Cookie的内容

同样的Cookie的内容的字符限制针对不同的Cookie版本也有不同。在Cookie Version 0中,某些特殊的字符,例如:空格,方括号,圆括号,等于号(=),逗号,双引号,斜杠,问号,@符号,冒号,分号都不能作为Cookie的内容。虽然在Cookie Version 1规定中放宽了限制,可以使用这些字符,但是考虑到新版本的Cookie规范目前仍然没有为所有的浏览器所支持,因而为保险起见,我们应该在Cookie的内容中尽量避免使用这些字符。

RFC2109 制定的规范:

Cookie:java.lang.IllegalArgumentException: An invalid character [32] was present in the Cookie value

RFC 2068 制定的规范:

Cookie:java.lang.IllegalArgumentException: An invalid character [32] was present in the Cookie value


Cookie中永远不要存特殊字符,即使要存储也要进行编码以后再存。


【参考】

HTTP cookie: https://en.wikipedia.org/wiki/HTTP_cookie
关于cookie特殊字符的一点理解: http://www.blogjava.net/stone2083/archive/2010/11/03/336923.html

相关标签: cookie