Cookie http only with spring security and servlet 2.5?
Solution 1
I hate XML configuration, so i spend some time for find non-XML solution.
Since Spring Security 1.3 you can use
server.session.cookie.http-only=true
server.session.cookie.secure=true
in your application.properties file.
Maybe there is a way to set this using pure Java Configuration, but i can't find them.
Solution 2
We ran across this issue recently. I tried the property settings for http-only, which worked locally, but not when we deployed to our test env. It's possible there were some default settings in the env overriding those local settings. What worked was to set the properties in a Spring config file:
@Bean
public ServletContextInitializer servletContextInitializer() {
return new ServletContextInitializer() {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.setSessionTrackingModes(Collections.singleton(SessionTrackingMode.COOKIE));
SessionCookieConfig sessionCookieConfig = servletContext.getSessionCookieConfig();
sessionCookieConfig.setHttpOnly(true);
sessionCookieConfig.setSecure(true);
}
};
}
Solution 3
The context.xml changes mentioned by javagc will only reconfigure your session cookie.
To change all of your cookies, you have 2 options:
Option 1) Update your application code to add cookies using a more secure method. Example: https://stackoverflow.com/a/30488471/95674
Option 2) You can configure a servlet filter to change ALL (other) cookies coming through the system. Add these 2 classes into the appropriate package in your WAR. Then update your web.xml as detailed below.
There is a simpler example of Option 2 listed on the OWASP site, if you are willing to add a dependency on the OWASP libraries. That is located here: https://www.owasp.org/index.php/HttpOnly#Using_Java_to_Set_HttpOnly
Response Wrapper
This adds the http only flag to all cookies on the wrapped response.
public class HttpOnlyResponseWrapper extends HttpServletResponseWrapper {
public HttpOnlyResponseWrapper(HttpServletResponse res) {
super(res);
}
public void addCookie(Cookie cookie) {
StringBuilder header = new StringBuilder();
if ((cookie.getName() != null) && (!cookie.getName().equals(""))) {
header.append(cookie.getName());
}
if (cookie.getValue() != null) {
// Empty values allowed for deleting cookie
header.append("=" + cookie.getValue());
}
if (cookie.getVersion() == 1) {
header.append(";Version=1");
if (cookie.getComment() != null) {
header.append(";Comment=\"" + cookie.getComment() + "\"");
}
if (cookie.getMaxAge() > -1) {
header.append(";Max-Age=" + cookie.getMaxAge());
}
} else {
if (cookie.getMaxAge() > -1) {
Date now = new Date();
now.setTime(now.getTime() + (1000L * cookie.getMaxAge()));
SimpleDateFormat cookieFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss zzz");
header.append(";Expires=" + cookieFormat.format(now));
}
}
if (cookie.getDomain() != null) {
header.append(";Domain=" + cookie.getDomain());
}
if (cookie.getPath() != null) {
header.append(";Path=" + cookie.getPath());
}
if (cookie.getSecure()) {
header.append(";Secure");
}
header.append(";httpOnly");
addHeader("Set-Cookie", header.toString());
}
}
Filter
This Filter wraps configured responses in the above wrapper.
package yourpackage;
@WebFilter(filterName = "HttpOnlyFilter", urlPatterns = {"/*"})
public class HttpOnlyFilter implements Filter {
private FilterConfig config;
@Override
public void destroy() {
this.config = null;
}
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpOnlyResponseWrapper hres = new HttpOnlyResponseWrapper((HttpServletResponse)res);
chain.doFilter(req, hres);
}
public FilterConfig getFilterConfig() {
return this.config;
}
@Override
public void init(FilterConfig config) throws ServletException {
this.config = config;
}
}
Adapted (WARNING: NOT an exact copy!) from source: http://sylvanvonstuppe.blogspot.com/2007/07/servlet-filter-for-httponly.html
web.xml
One last detail: ONLY IF you have annotation scanning turned OFF in your system like this:
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
version="2.5" ***metadata-complete="true"***>
</web-app>
Then you will need to manually configure the above Filter in your web.xml file, like this:
<filter>
<filter-name>HttpOnlyFilter
<filter-class>yourpackage.HttpOnlyFilter
</filter>
<filter-mapping>
<filter-name>HttpOnlyFilter
<url-pattern>/*
</filter-mapping>
If your app scans annotations (which is the default), the web.xml part is not necessary.
jpganz18
Updated on July 20, 2022Comments
-
jpganz18 almost 2 years
I want to make my cookie secure and http request only.
Ive seen many post like this and seem to work fine, but using configuration files and servlet +3.
What I basically want to do is to set my cookie http only and (if possible) ssl only as well.
So far I added this to my web.xml
<session-config> <session-timeout>60</session-timeout> <cookie-config> <http-only>true</http-only> </cookie-config> <tracking-mode>COOKIE</tracking-mode> </session-config>
doesnt do anything, as far as I was reading, I also have to configure my servlet.xml to enable this feature, but I dont know how...
Any idea how to do this?
EDIT:
Since I am using servlets 2.5 the xml configuration is not an option, maybe a filter?
-
jpganz18 about 8 yearsThanks, but this should not make any difference on the configuration
-
jpganz18 about 8 yearsHello, I saw the first option, but have no idea where to se it... is it the best approach? I saw the class... but , I add it to a filter?
-
jpganz18 about 8 yearsthe filter works smoothly! just wondering, how can I set the domain name or the secure = true if not using the xml configuration anymore? or just hardcoding them into the class?
-
Barett about 8 yearsThe XML configuration is only for the session cookie; it does not apply to all cookies set by your application. If you want to set the domain or secure values for cookies set by your app, you'll need to set them on the cookie itself. I've used a subclass of Cookie to do this in the past. (
public class MyCookie extends Cookie
, sets default values for domain/secure in the constructor. Add getters & setters that call super for everything, then make sure everyone uses this instead of Cookie.) -
Anand Rockzz about 5 years
java.lang.UnsupportedOperationException: Section 4.4 of the Servlet 3.0 specification does not permit this method to be called from a ServletContextListener that was not defined in web.xml, a web-fragment.xml file nor annotated with @WebListener
atevent.getServletContext().getSessionCookieConfig();
-
Khoa Phung almost 5 yearsThese configurations is deprecated