JavaServlet-当Servlet是安全的时,不同的JSESSION ID。为什么?

JavaServlet-当Servlet是安全的时,不同的JSESSION ID。为什么?,java,tomcat,servlets,web.xml,jsessionid,Java,Tomcat,Servlets,Web.xml,Jsessionid,我删除了我以前的帖子,重新创建了一个更清晰的版本。作为参考,我简化了代码以使其更简单 我向你提出我的问题 我的servlet HelloWorld: public class HelloWorld extends HttpServlet { private String message; public void init() throws ServletException { // Do required initialization mess

我删除了我以前的帖子,重新创建了一个更清晰的版本。作为参考,我简化了代码以使其更简单

我向你提出我的问题

我的servlet HelloWorld:

public class HelloWorld extends HttpServlet {

    private String message;

    public void init() throws ServletException {
        // Do required initialization
        message = "Hello World";
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // Set response content type
        response.setContentType("text/html");

        // session test
        System.out.println( request.getSession().getId() );

        PrintWriter out = response.getWriter();
        out.println("<html><head><script src='./dwr/engine.js'></script><script src='./dwr/util.js'></script></head><body><h1>Hello World</h1></body></html>");
    }

    public void destroy() {
        // do nothing.
    }
}
公共类HelloWorld扩展了HttpServlet{
私有字符串消息;
public void init()引发ServletException{
//执行所需的初始化
message=“你好,世界”;
}
public void doGet(HttpServletRequest请求、HttpServletResponse响应)
抛出ServletException、IOException{
//设置响应内容类型
response.setContentType(“text/html”);
//会话测试
System.out.println(request.getSession().getId());
PrintWriter out=response.getWriter();
out.println(“你好世界”);
}
公共空间销毁(){
//什么也不做。
}
}
servlet显示一个包含消息HellWorld的html页面,并包含DWR(直接Web远程处理)javascript文件。DWR javascript文件是从servlet/DWR/检索的

Web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
    <display-name>TestDWR2</display-name>

    <servlet>
        <servlet-name>HelloWorld</servlet-name>
        <servlet-class>test.HelloWorld</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>HelloWorld</servlet-name>
        <url-pattern>/HelloWorld/*</url-pattern>
    </servlet-mapping>

    <servlet>
      <servlet-name>dwr-invoker</servlet-name>
      <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
        <init-param>
            <param-name>config</param-name>
            <param-value>WEB-INF/dwr.xml</param-value>
        </init-param>
        <init-param>
            <param-name>debug</param-name>
            <param-value>true</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
      <servlet-name>dwr-invoker</servlet-name>
      <url-pattern>/dwr/*</url-pattern>
    </servlet-mapping>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Extranet resource</web-resource-name>
            <description>Extranet resources</description>
            <url-pattern>/HelloWorld/*</url-pattern>
            <url-pattern>/dwr/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>intranet_admin</role-name>
        </auth-constraint>
    </security-constraint>

    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>Extranet</realm-name>
    </login-config>

    <security-role>
        <description>Intranet Admin</description>
        <role-name>intranet_admin</role-name>
    </security-role>

</web-app>

TestDWR2
你好世界
test.HelloWorld
你好世界
/地狱世界/*
dwr调用程序
org.directwebremoting.servlet.DwrServlet
配置
WEB-INF/dwr.xml
调试
真的
dwr调用程序
/dwr/*
外联网资源
外联网资源
/地狱世界/*
/dwr/*

您可以在此链接上找到代码源:


非常感谢。

我没有检查wars,但这可能是一个会话固定问题,在Tomcat 7中默认情况下是打开的。当会话通过身份验证时,它基本上会更改会话ID。查看更多信息,然后尝试关闭,看看这是否是您的问题确实,如果我在Context.xml中设置changesessiondonauthentication=“false”,它会起作用:

    <web-resource-collection>
        <web-resource-name>Extranet resource</web-resource-name>
        <description>Extranet resources</description>
        <url-pattern>/HelloWorld/*</url-pattern>
        <url-pattern>/dwr/*</url-pattern>
    </web-resource-collection>
<Context path="/test" reloadable="true" docBase="D:\projects\test2\TestDWR" workDir="D:\projects\test2\TestDWR\work" >
<Valve className="org.apache.catalina.authenticator.BasicAuthenticator"
  changeSessionIdOnAuthentication="false" />
</Context>

但我看到http请求被发出了两次:

是否有另一种不会危及安全的解决方案?Servlet过滤器还是其他

它实际上是阻塞的,因为在第一次从数据库检索数据并在会话中设置它们时。在第二个请求中,由于jsessionid更改,数据不再处于会话中,必须再次检索


感谢您的帮助

我认为这与防止会话固定有关。通常,每次进行身份验证时都会生成一个新的sessionid,以确保没有其他人拥有旧的(不安全的)会话id并突然登录。基本身份验证似乎会登录每个请求,从而更改会话ID。也许有一个会话处理程序丢失了,如果会话仍然有效,它会跳过BA——但我不确定是否在Detault上。这是哪只tomcat?它对阀门和过滤器有任何全局性的改变吗?您使用的领域是什么?如果我在Context.xml中设置changesessiondonauthentication=“false”,它会工作,但如果可能的话,我希望保持这种安全性。您是否有其他解决方案来保护安全性?Servlet过滤器?会话处理程序?我使用Tomcat7。我使用org.apache.catalina.realm.UserDatabaseRealm。感谢您的帮助我想一定有办法将tomcat配置为在会话存在/有效时跳过(重新)身份验证。但是我不知道如何:)事实上,如果我在Context.xml中设置changesessiondonauthentication=“false”,它就可以工作了。非常感谢。是否有另一种不会危及安全的解决方案?Servlet过滤器还是其他?我回答我的问题以添加http请求/响应捕获。浏览器在没有BA的情况下尝试是正常的,当它获得401时,它将使用授权标头重试。我不知道为什么浏览器会对子资源这样做,但哦,好吧……)
<Context path="/test" reloadable="true" docBase="D:\projects\test2\TestDWR" workDir="D:\projects\test2\TestDWR\work" >
<Valve className="org.apache.catalina.authenticator.BasicAuthenticator"
  changeSessionIdOnAuthentication="false" />
</Context>