我需要在Google App Engine中的会话cookie上设置httpOnly和安全标记。
我在web.xml
中尝试了以下内容:
<session-config>
<cookie-config>
<http-only>true</http-only>
</cookie-config>
</session-config>
但是,这不起作用。
我也在每个JSP的顶部尝试过这个:
String sessionid = request.getSession().getId();
response.setHeader("SET-COOKIE", "JSESSIONID=" + sessionid + "; HttpOnly");
我怎样才能做到这一点?
答案 0 :(得分:6)
我在使用Google App Engine时遇到了同样的问题,但我想在所有Cookie中添加Secure
属性。以下显示了我如何为所有Cookie添加Secure
属性。我几乎可以肯定,只需用Secure
代替HttpOnly
,这个解决方案就能为您服务。
我已经实现了一个安全过滤器并映射到了我希望设置Secure
属性的页面。
<filter>
<filter-name>Security Filter</filter-name>
<filter-class>common.SecurityFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Security Filter</filter-name>
<url-pattern>*.jsf</url-pattern>
</filter-mapping>
我的第一次尝试是将回复包装到我的自定义HttpServletResponseWrapper
中。一切都很好,除了会话cookie没有得到属性。我调试了一下,发现会话cookie没有使用我预期的机制添加。我注意到,在您触摸会话后,会话cookie被神奇地添加到响应标头中,例如标题现在由行Set-Cookie: JSESSIONID=abcdef;Path=/
组成,但是没有使用我创建的包装器对象添加cookie。我已经发现,在我触及会话后,我可以使用我想要的属性设置我想要的cookie。所以解决方法很简单。
public class SecurityFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// wrap the response
response = new SecureCookieSetter((HttpServletResponse)response);
// touch the session
(HttpServletRequest)request.getSession();
// overwriting the cookie with Secure attribute set
((HttpServletResponse)response).setHeader("Set-Cookie", "JSESSIONID=" + ((HttpServletRequest)request).getSession().getId() + ";Path=/");
}
}
public class SecureCookieSetter extends HttpServletResponseWrapper {
public SecureCookieSetter(HttpServletResponse response) {
super(response);
}
@Override
public void addCookie(Cookie cookie) {
cookie.setSecure(true);
super.addCookie(cookie);
}
@Override
public void addHeader(String name, String value) {
if ((name.equals("Set-Cookie")) && (!value.matches("(^|.*;)\\s*Secure"))) {
value = value + ";Secure";
}
super.addHeader(name, value);
}
@Override
public void setHeader(String name, String value) {
if ((name.equals("Set-Cookie")) && (!value.matches("(^|.*;)\\s*Secure"))) {
value = value + ";Secure";
}
super.setHeader(name, value);
}
}
答案 1 :(得分:1)
我在使用Java 7和Servlet 2.5的Google App Engine中遇到了同样的问题,即将HttpOnly
和Secure
属性添加到会话Cookie中。我遵循了@bat_venti的回答-很有帮助,谢谢! -但在使其工作时遇到了一些麻烦,所以我要发布自己的答案:)
我创建了一个SecurityFilter
类,将会话cookie属性应用于.jsp
请求,如下所示:
import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.IOException;
public class SecurityFilter implements javax.servlet.Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void destroy() {}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// wrap the response
response = new SecureCookieSetter((HttpServletResponse)response);
// touch the session
((HttpServletRequest) request).getSession();
// overwriting the cookie with Secure and HttpOnly attribute set
((HttpServletResponse)response).setHeader("Set-Cookie", "JSESSIONID=" + ((HttpServletRequest)request).getSession().getId() + ";Path=/");
chain.doFilter(request, response);
}
public class SecureCookieSetter extends HttpServletResponseWrapper {
public SecureCookieSetter(HttpServletResponse response) {
super(response);
}
@Override
public void addCookie(Cookie cookie) {
cookie.setSecure(true);
super.addCookie(cookie);
}
@Override
public void addHeader(String name, String value) {
if ((name.equals("Set-Cookie")) && (!value.matches("(^|.*;)\\s*Secure"))) {
value = value + ";Secure;HttpOnly";
}
super.addHeader(name, value);
}
@Override
public void setHeader(String name, String value) {
if ((name.equals("Set-Cookie")) && (!value.matches("(^|.*;)\\s*Secure"))) {
value = value + ";Secure;HttpOnly";
}
super.setHeader(name, value);
}
}
}
(我在内部创建了SecureCookieSetter
类,因为我只会在此过滤器中使用它,但是可以将其放在自己的文件中)。
之后,我编辑了web.xml
文件以在请求.jsp
文件时使用过滤器:
<web-app>
...
<filter>
<filter-name>SecurityFilter</filter-name>
<filter-class>path.to.my.filter.SecurityFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SecurityFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
...
</web-app>
(显然,将path.to.my.filter
替换为类文件的实际位置)。
答案 2 :(得分:0)
就我而言,SecureCookieSetter类没有被使用。我还将我的Java Web应用程序运行到GAE中。 下面是在我的情况下工作正常的代码。同样,它总是建议使用其他与安全性相关的标头,例如max-age和以下标头。
package com.securityFilter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import com.filters.XSSRequestWrapper;
public class SecurityFilter implements Filter {
protected static final Logger log = Logger.getLogger(SecurityFilter.class);
private static final String PRAGMA_KEY = "Pragma";
private static final String PRAGMA_VALUE = "no-cache";
private static final String STRICT_TRANSPORT_KEY = "strict-transport-security";
private static final String STRICT_TRANSPORT_VALUE = "max-age=604800";
private static final String SET_COOKIE = "Set-Cookie";
private static final String JSESSION_ID = "JSESSIONID=";
private static final String HTTP_ONLY = ";Secure;HttpOnly";
private static final String CACHE_CONTROL_KEY = "Cache-Control";
private static final String CACHE_CONTROL_VALUE = "no-store";
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
makeCookieSecured(response, httpServletRequest);
chain.doFilter(request, response);
}
private void makeCookieSecured(ServletResponse response,
HttpServletRequest httpServletRequest) {
Cookie[] cookies = httpServletRequest.getCookies();
HttpServletResponse httpResp = ((HttpServletResponse) response);
if (cookies != null) {
for(Cookie cookie :cookies){
if("JSESSIONID".equals(cookie.getName())) {
cookie.setValue(httpServletRequest.getSession().getId() + HTTP_ONLY);
cookie.setSecure(true);
cookie.setPath("/");
cookie.setMaxAge(604800);
}
}
}
httpResp.setHeader(SET_COOKIE, JSESSION_ID + httpServletRequest.getSession().getId() + HTTP_ONLY);
httpResp.setHeader(CACHE_CONTROL_KEY, CACHE_CONTROL_VALUE);
httpResp.setHeader(PRAGMA_KEY, PRAGMA_VALUE);
httpResp.setHeader(STRICT_TRANSPORT_KEY, STRICT_TRANSPORT_VALUE);
}
private void createJSONErrorResponse(ServletResponse response)
throws IOException {
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().write("Please provide valid input, You might have provided some special characters which is not allowed");
}
@Override
public void destroy() {
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}