Como você configura cookies HttpOnly em webapps tomcat/java?
Pergunta
Depois de ler a postagem do blog de Jeff em Protegendo seus cookies:Somente http.Gostaria de implementar cookies HttpOnly em meu aplicativo da web.
Como você diz ao Tomcat para usar cookies somente http para sessões?
Solução
httpOnly é suportado a partir do Tomcat 6.0.19 e Tomcat 5.5.28.
Veja o registro de alterações entrada para bug 44382.
O último comentário para bug 44382 Estados, "Isso foi aplicado a 5.5.x e será incluído em 5.5.28 em diante". No entanto, não parece que o 5.5.28 tenha sido lançado.
A funcionalidade httpOnly pode ser habilitada para todos os webapps em conf/context.xml:
<Context useHttpOnly="true">
...
</Context>
Minha interpretação é que isso também funciona para um contexto individual, configurando-o no desejado Contexto entrada em conf/servidor.xml (da mesma maneira acima).
Outras dicas
Atualizar:O material do JSessionID aqui é apenas para contêineres mais antigos.Use a resposta atualmente aceita do JT, a menos que você esteja usando <TomCat 6.0.19 ou <Tomcat 5.5.28 ou outro contêiner que não suporta httponly jsessionId Cookies como uma opção de configuração.
Ao definir cookies em seu aplicativo, use
response.setHeader( "Set-Cookie", "name=value; HttpOnly");
No entanto, em muitas aplicações web, o cookie mais importante é o identificador de sessão, que é automaticamente definido pelo contêiner como o cookie JSESSIONID.
Se você usar apenas este cookie, poderá escrever um ServletFilter para redefinir os cookies na saída, forçando JSESSIONID a HttpOnly.A página em http://keepitlocked.net/archive/2007/11/05/java-and-httponly.aspx http://alexsmolen.com/blog/?p=16 sugere adicionar o seguinte em um filtro.
if (response.containsHeader( "SET-COOKIE" )) {
String sessionid = request.getSession().getId();
response.setHeader( "SET-COOKIE", "JSESSIONID=" + sessionid
+ ";Path=/<whatever>; Secure; HttpOnly" );
}
mas observe que isso substituirá todos os cookies e definirá apenas o que você indicar aqui neste filtro.
Se você usar cookies adicionais ao cookie JSESSIONID, precisará estender esse código para definir todos os cookies no filtro.Esta não é uma ótima solução no caso de vários cookies, mas talvez seja uma solução rápida aceitável para a configuração somente JSESSIONID.
Observe que, à medida que seu código evolui com o tempo, há um bug oculto desagradável esperando por você quando você esquecer esse filtro e tentar definir outro cookie em algum outro lugar do seu código.Claro, não será definido.
Isso realmente é um hack.Se você usa o Tomcat e pode compilá-lo, dê uma olhada na excelente sugestão do Shabaz para corrigir o suporte HttpOnly no Tomcat.
Tenha cuidado para não substituir o sinalizador de cookie ";secure" em sessões https.Esse sinalizador impede que o navegador envie o cookie por meio de uma conexão http não criptografada, basicamente tornando inútil o uso de https para solicitações legítimas.
private void rewriteCookieToHeader(HttpServletRequest request, HttpServletResponse response) {
if (response.containsHeader("SET-COOKIE")) {
String sessionid = request.getSession().getId();
String contextPath = request.getContextPath();
String secure = "";
if (request.isSecure()) {
secure = "; Secure";
}
response.setHeader("SET-COOKIE", "JSESSIONID=" + sessionid
+ "; Path=" + contextPath + "; HttpOnly" + secure);
}
}
Para cookies de sessão, ainda não parece ser suportado no Tomcat.Veja o relatório de erros É necessário adicionar suporte para parâmetro de cookie de sessão HTTPOnly.Uma solução alternativa um tanto complicada por enquanto pode ser encontrada aqui, que basicamente se resume a corrigir manualmente o Tomcat.Realmente não consigo encontrar uma maneira fácil de fazer isso neste momento, neste momento, estou com medo.
Para resumir a solução alternativa, envolve o download do 5.5 fonte, e altere a origem nos seguintes locais:
org.apache.catalina.connector.Request.java
//this is what needs to be changed
//response.addCookieInternal(cookie);
//this is whats new
response.addCookieInternal(cookie, true);
}
org.apache.catalina.connectorResponse.addCookieInternal
public void addCookieInternal(final Cookie cookie) {
addCookieInternal(cookie, false);
}
public void addCookieInternal(final Cookie cookie, boolean HTTPOnly) {
if (isCommitted())
return;
final StringBuffer sb = new StringBuffer();
//web application code can receive a IllegalArgumentException
//from the appendCookieValue invokation
if (SecurityUtil.isPackageProtectionEnabled()) {
AccessController.doPrivileged(new PrivilegedAction() {
public Object run(){
ServerCookie.appendCookieValue
(sb, cookie.getVersion(), cookie.getName(),
cookie.getValue(), cookie.getPath(),
cookie.getDomain(), cookie.getComment(),
cookie.getMaxAge(), cookie.getSecure());
return null;
}
});
} else {
ServerCookie.appendCookieValue
(sb, cookie.getVersion(), cookie.getName(), cookie.getValue(),
cookie.getPath(), cookie.getDomain(), cookie.getComment(),
cookie.getMaxAge(), cookie.getSecure());
}
//of course, we really need to modify ServerCookie
//but this is the general idea
if (HTTPOnly) {
sb.append("; HttpOnly");
}
//if we reached here, no exception, cookie is valid
// the header name is Set-Cookie for both "old" and v.1 ( RFC2109 )
// RFC2965 is not supported by browsers and the Servlet spec
// asks for 2109.
addHeader("Set-Cookie", sb.toString());
cookies.add(cookie);
}
Se o seu servidor web suportar a especificação Serlvet 3.0, como Tomcat 7.0+, você pode usar abaixo em web.xml
como:
<session-config>
<cookie-config>
<http-only>true</http-only>
<secure>true</secure>
</cookie-config>
</session-config>
Conforme mencionado nos documentos:
Somente http:Especifica se algum cookies de rastreamento de sessão criado por este aplicativo da Web será marcado como httponly
Seguro:Especifica se algum cookies de rastreamento de sessão criado por este aplicativo da Web será marcado como seguro, mesmo se a solicitação que iniciou a sessão correspondente estiver usando HTTP simples em vez de https
Consulte como definir httponly e cookie de sessão para aplicativos da web java
também deve ser observado que ativar o HttpOnly interromperá os miniaplicativos que exigem acesso com estado de volta ao jvm.
as solicitações http do miniaplicativo não usarão o cookie jsessionid e poderão ser atribuídas a um tomcat diferente.
Para cookies que estou configurando explicitamente, mudei para usar Biscoito Simples fornecido por Apache Shiro.Ele não herda de javax.servlet.http.Cookie, portanto, é preciso um pouco mais de malabarismo para que tudo funcione corretamente, no entanto, ele fornece um conjunto de propriedades HttpOnly e funciona com o Servlet 2.5.
Para definir um cookie em uma resposta, em vez de fazer response.addCookie(cookie)
você precisa fazer cookie.saveTo(request, response)
.
No Tomcat6, você pode habilitar condicionalmente em sua classe de ouvinte HTTP:
public void contextInitialized(ServletContextEvent event) {
if (Boolean.getBoolean("HTTP_ONLY_SESSION")) HttpOnlyConfig.enable(event);
}
Usando esta classe
import java.lang.reflect.Field;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import org.apache.catalina.core.StandardContext;
public class HttpOnlyConfig
{
public static void enable(ServletContextEvent event)
{
ServletContext servletContext = event.getServletContext();
Field f;
try
{ // WARNING TOMCAT6 SPECIFIC!!
f = servletContext.getClass().getDeclaredField("context");
f.setAccessible(true);
org.apache.catalina.core.ApplicationContext ac = (org.apache.catalina.core.ApplicationContext) f.get(servletContext);
f = ac.getClass().getDeclaredField("context");
f.setAccessible(true);
org.apache.catalina.core.StandardContext sc = (StandardContext) f.get(ac);
sc.setUseHttpOnly(true);
}
catch (Exception e)
{
System.err.print("HttpOnlyConfig cant enable");
e.printStackTrace();
}
}
}
Eu encontrei em OWASP
<session-config>
<cookie-config>
<http-only>true</http-only>
</cookie-config>
</session-config>
isso também é uma correção para o problema de segurança "httponlycookies in config"