Java 如何在 servlet 响应中添加多个“Set-Cookie”标头?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31046203/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to add multiple "Set-Cookie" header in servlet response?
提问by gauravphoenix
As per RFC http://tools.ietf.org/html/rfc6265#page-7It is allowed to have two headers with same key of "Set-Cookie". The example provided in RFC is -
根据 RFC http://tools.ietf.org/html/rfc6265#page-7允许有两个具有相同“Set-Cookie”键的标头。RFC 中提供的示例是 -
??Set-Cookie: SID=31d4d96e407aad42; Path=/; Secure; HttpOnly
Set-Cookie: ??lang=en-US; Path=/; Domain=example.com
How? do ?I achieve same with Jetty(or any other servlet container)? When I call httpServletResponse.addHeader this way-
如何?做什么?我用 Jetty(或任何其他 servlet 容器)实现了相同的目标?当我以这种方式调用 httpServletResponse.addHeader 时-
?httpServletResponse.addHeader("Set-Cookie", "SID=31d4d96e407aad42; Path=/; Secure; HttpOnly");
httpServletResponse.addHeader("Set-Cookie", "lang=en-US; Path=/; Domain=example.com");?
I see that the second addHeader() doesn't add a new header. According to javadoc for this method-
我看到第二个 addHeader() 没有添加新标题。根据此方法的javadoc-
Adds a response header with the given name and value. This method allows response headers to have multiple values.
添加具有给定名称和值的响应标头。此方法允许响应标头具有多个值。
So it seems that multiple values of allowed but I am not sure how to go about having multiple "Set-Cookie" in servlet response.
因此,似乎有多个 allowed 值,但我不确定如何在 servlet 响应中使用多个“Set-Cookie”。
采纳答案by Joakim Erdfelt
Setting Cookies directly like that is a bit awkward, considering that the Servlet API has methods specifically for working with Cookies.
考虑到 Servlet API 有专门用于处理 Cookie 的方法,像这样直接设置 Cookie 有点尴尬。
Anyway, tested on Jetty 9.3.0.v20150612 and it works as expected.
无论如何,在 Jetty 9.3.0.v20150612 上测试,它按预期工作。
Example: SetCookieTest.java
示例:SetCookieTest.java
package jetty;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class SetCookieTest
{
@SuppressWarnings("serial")
public static class SetCookieAddHeaderServlet extends HttpServlet
{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
resp.setContentType("text/plain");
resp.addHeader("Set-Cookie","SID=31d4d96e407aad42; Path=/; Secure; HttpOnly");
resp.addHeader("Set-Cookie","lang=en-US; Path=/; Domain=example.com");
PrintWriter out = resp.getWriter();
out.println("Hello From: " + this.getClass().getName());
}
}
@SuppressWarnings("serial")
public static class SetCookieAddCookieServlet extends HttpServlet
{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
resp.setContentType("text/plain");
// Set-Cookie: SID=31d4d96e407aad42; Path=/; Secure; HttpOnly
Cookie sidCookie = new Cookie("SID","31d4d96e407aad42");
sidCookie.setPath("/");
sidCookie.setSecure(true);
sidCookie.setHttpOnly(true);
resp.addCookie(sidCookie);
// Set-Cookie: lang=en-US; Path=/; Domain=example.com
Cookie langCookie = new Cookie("lang","en-US");
langCookie.setPath("/");
langCookie.setDomain("example.com");
resp.addCookie(langCookie);
PrintWriter out = resp.getWriter();
out.println("Hello From: " + this.getClass().getName());
}
}
private static Server server;
@BeforeClass
public static void startServer() throws Exception
{
server = new Server(9090);
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.addServlet(SetCookieAddHeaderServlet.class,"/test-add-header");
context.addServlet(SetCookieAddCookieServlet.class,"/test-add-cookie");
server.setHandler(context);
server.start();
}
@AfterClass
public static void stopServer() throws Exception
{
server.stop();
}
/**
* Issue simple GET request, returning entire response (including payload)
*
* @param uri
* the URI to request
* @return the response
*/
private String issueSimpleHttpGetRequest(String path) throws IOException
{
StringBuilder req = new StringBuilder();
req.append("GET ").append(path).append(" HTTP/1.1\r\n");
req.append("Host: localhost\r\n");
req.append("Connection: close\r\n");
req.append("\r\n");
// Connect
try (Socket socket = new Socket("localhost",9090))
{
try (OutputStream out = socket.getOutputStream())
{
// Issue Request
byte rawReq[] = req.toString().getBytes(StandardCharsets.UTF_8);
out.write(rawReq);
out.flush();
// Read Response
StringBuilder resp = new StringBuilder();
try (InputStream stream = socket.getInputStream();
InputStreamReader reader = new InputStreamReader(stream);
BufferedReader buf = new BufferedReader(reader))
{
String line;
while ((line = buf.readLine()) != null)
{
resp.append(line).append(System.lineSeparator());
}
}
// Return Response
return resp.toString();
}
}
}
@Test
public void testAddHeader() throws Exception
{
String response = issueSimpleHttpGetRequest("/test-add-header");
System.out.println(response);
assertThat("response", response, containsString("Set-Cookie: SID=31d"));
assertThat("response", response, containsString("Set-Cookie: lang=en-US"));
}
@Test
public void testAddCookie() throws Exception
{
String response = issueSimpleHttpGetRequest("/test-add-cookie");
System.out.println(response);
assertThat("response", response, containsString("Set-Cookie: SID=31d"));
assertThat("response", response, containsString("Set-Cookie: lang=en-US"));
}
}
Console Output
控制台输出
2015-06-25 14:18:19.186:INFO::main: Logging initialized @167ms
2015-06-25 14:18:19.241:INFO:oejs.Server:main: jetty-9.3.0.v20150612
2015-06-25 14:18:19.276:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@56cbfb61{/,null,AVAILABLE}
2015-06-25 14:18:19.288:INFO:oejs.ServerConnector:main: Started ServerConnector@1ef05443{HTTP/1.1,[http/1.1]}{0.0.0.0:9090}
2015-06-25 14:18:19.289:INFO:oejs.Server:main: Started @270ms
HTTP/1.1 200 OK
Date: Thu, 25 Jun 2015 21:18:19 GMT
Content-Type: text/plain;charset=iso-8859-1
Set-Cookie: SID=31d4d96e407aad42;Path=/;Secure;HttpOnly
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Set-Cookie: lang=en-US;Path=/;Domain=example.com
Connection: close
Server: Jetty(9.3.0.v20150612)
Hello From: jetty.SetCookieTest$SetCookieAddCookieServlet
HTTP/1.1 200 OK
Date: Thu, 25 Jun 2015 21:18:19 GMT
Content-Type: text/plain;charset=iso-8859-1
Set-Cookie: SID=31d4d96e407aad42; Path=/; Secure; HttpOnly
Set-Cookie: lang=en-US; Path=/; Domain=example.com
Connection: close
Server: Jetty(9.3.0.v20150612)
Hello From: jetty.SetCookieTest$SetCookieAddHeaderServlet
2015-06-25 14:18:19.405:INFO:oejs.ServerConnector:main: Stopped ServerConnector@1ef05443{HTTP/1.1,[http/1.1]}{0.0.0.0:9090}
2015-06-25 14:18:19.407:INFO:oejsh.ContextHandler:main: Stopped o.e.j.s.ServletContextHandler@56cbfb61{/,null,UNAVAILABLE}
回答by defectus
It's probably not the answer you're looking for but I just tried this myself and it worked right away:
这可能不是您正在寻找的答案,但我自己刚刚尝试过,它立即起作用:
Set-Cookie:SID=31d4d96e407aad42; Path=/; Secure; HttpOnly
Set-Cookie:lang=en-US; Path=/; Domain=example.com
Set-Cookie:JSESSIONID=76A68D96ED044DDFF0CC266810F52DDA; Path=/; HttpOnly
That's how the response looked like. Maybe it's the problem of your particular web container, or your implementation.
这就是响应的样子。也许这是您的特定 Web 容器或您的实现的问题。
Try to debug the application (using remote debugging facility) to figure out where the header gets lost.
尝试调试应用程序(使用远程调试工具)以找出标头丢失的位置。