Java servlet session 无法与 NGinx 正常工作,如何修复?

标签 java session servlets nginx

我有一个运行 Java servlet 的站点,使用 tomcat8.5,它工作正常:http://69.197.177.154:8080/GATE_Web/index.jsp

但是 ISP 的人担心安全性,所以他建议我们使用 NGinx 来使其更安全,因此同一个应用程序正在执行 NGinx 代理传递,并且运行在:http://gatecybertech.net/

它运行不正常,当我单击按钮时,底部的光标没有移动,并且我注意到页面右上角的“用户数:”正在快速增加,即使有只有一个用户 [我] 测试该应用程序。我使用 Java session 来跟踪新用户 session ,它在第一个站点中工作正常,但在使用 NGinx 时,它的行为不正确。

由于该应用程序很复杂,为了快速找出它无法与 NGinx 正常工作的原因,我简化了该应用程序并创建了另一个名为 Test_Servlet 的 servlet:http://69.197.177.154:8080/GATE_Web/Test_Servlet

正如您所看到的,当您单击不同的按钮时,光标会跟随并指向单击的按钮。

与 NGinx 一起运行的相同 Test_Servlet 位于:http://gatecybertech.net/Test_Servlet

使用此按钮,光标将不会跟随您单击的按钮。

我怀疑 NGinx 的配置设置不正确,您认为哪里出了问题?

这是简化的 servlet。

import java.io.*;
import java.net.*;

import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
import Utility.*;

public class Test_Servlet extends HttpServlet
{
  private boolean Debug=false;
  String App_Id="Test_Servlet",GATE_Title,User_Id=null,Profile="Profile",requestMethod,
         Spaces_Text="&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;",Line_Breaks="<P><Br>\n<P><Br>\n<P><Br>\n<P><Br>\n<P><Br>\n<P><Br>\n<P><Br>\n";

  public Test_Servlet()
  {
    super();

    GATE_Title="<Table Border=0 Cellpadding=0 Cellspacing=8>\n"+
               "  <Tr><Td Align=Center><Font Color=#3636CC Size=2>Server : [Server_Info] "+Spaces_Text+" User Count : [User_Count]</Font></Td></Tr>\n"+
               "</Table>\n";
  }

/** Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
 * @param request servlet request
 * @param response servlet response
 */
  private void processRequest(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException
  {
    HttpSession session=request.getSession(true);
    Session_Counter counter=(Session_Counter)session.getAttribute(Session_Counter.COUNTER); 
    int User_Count=counter.getActiveSessionNumber();

    String title="Test_Servlet",Server_Info=getServletContext().getServerInfo(),Action,Current_Id_Button,responseText,
           responseString="<!DOCTYPE html>\n"+
                          "<Html>\n"+
                          "<Head>\n"+
                          "  <Title>"+title+"</Title>\n"+
                          Get_jQuery()+
                          "  <Link rel=\"stylesheet\" type=\"text/css\" href=\"GATE_Style.css\">\n"+
                          "</Head>\n\n"+
                          "<Body BgColor=#C6DAFA>\n\n"+
                          "<Center>\n"+
                          "<P><Br><Br><P><Br><P><Br><P><Br><P><Br><P><Br><P><Br><P><Br><P><Br><P>\n"+
                          GATE_Title.replace("[Server_Info]",Server_Info).replace("[User_Count]",User_Count+"")+"<P><P>\n";
    LinkedHashMap<String,String> params=getQueryParameterMap(request);
    int Font_Size=20,Current_Id;

    requestMethod=request.getMethod()+"()";
      response.setContentType("text/html");
    response.setHeader("Content-Type","text/html;charset=utf-8");
      PrintWriter out=response.getWriter();
    try
    {
      User_Id=Decode_String(params.get("User_Id"));
      Action=Decode_String(params.get("Action"));
      Current_Id_Button=Decode_String(params.get("Current_Id_Button"));

      Debug=(params.get("Debug")==null?Debug:params.get("Debug").toLowerCase().equals("true"));

      if (session.getAttribute("Current_Id")==null)
      {
        Current_Id=1;
        session.setAttribute("Current_Id",Current_Id+"");          
      }
      else Current_Id=Integer.parseInt((String)session.getAttribute("Current_Id"));

      if (Action!=null && Action.equals("Get_Pointer_Table"))                       // Everytime after Current_Id change, adjust pointer table
      {
          out.print(Get_Pointer_Table(Current_Id));
//        Out(Get_Pointer_Table(Current_Id));
      }
      else if (Current_Id_Button!=null && Current_Id_Button.startsWith("Current_"))      // Current_Id Button is clicked, set Current_Id to it
      {
        Current_Id=Integer.parseInt(Current_Id_Button.substring(8));
        session.setAttribute("Current_Id",Current_Id+"");
      }
      else if (Action!=null && Action.equals("Current_Id"))                              // Everytime a symbols/token is clicked, increase Current_Id by one
      {
        responseText=Current_Id+"";
        if (Current_Id<6) Current_Id++;
        else Current_Id=1;
        session.setAttribute("Current_Id",Current_Id+"");
          out.println(responseText);
//        Out(" Current_Id = "+Current_Id);
      }
      else
      {
        responseString+=Get_Parameters(params)+"<P>\n";
        // Object does not exist or is not a file: reject with 404 error.
//        responseString+="404 (Not Found)\n";
        responseString+="<Br><P><Br><P><Br><P>\n";

        Current_Id=1;
        session.setAttribute("Current_Id",Current_Id+"");
        responseString+="<Table Border=0 Cellpadding=0 Cellspacing=0>\n"+
                        "  <Tr>\n"+
                        "    <Td>\n"+
                        "      <Table Border=0 Cellpadding=0 Cellspacing=3>\n"+
                        "        <Tr>\n"+
                        "          <Td>"+Get_Html_Button("Current_1","1",82,82,Font_Size)+"</Td>\n"+
                        "          <Td>"+Get_Html_Button("Current_2","2",82,82,Font_Size)+"</Td>\n"+
                        "          <Td>"+Get_Html_Button("Current_3","3",82,82,Font_Size)+"</Td>\n"+
                        "          <Td>"+Get_Html_Button("Current_4","4",82,82,Font_Size)+"</Td>\n"+
                        "          <Td>"+Get_Html_Button("Current_5","5",82,82,Font_Size)+"</Td>\n"+
                        "          <Td>"+Get_Html_Button("Current_6","6",82,82,Font_Size)+"</Td>\n"+
                        "        </Tr>\n"+
                        "      </Table>\n"+
                        "    </Td>\n"+
                        "  </Tr>\n"+
                        "  <Tr>\n"+
                        "    <Td>\n"+
                        Get_Pointer_Table(Current_Id)+
                        "    </Td>\n"+
                        "  </Tr>\n"+
                        "</Table>\n";
        responseString+="</div>\n";
        out.println(responseString);
//      Out(responseString);
      }
    }
    catch (Exception e)
    {
      if (!e.toString().equals("java.io.IOException: Broken pipe"))                      // When user closes a window while half way writing, gets a "Broken pipe"
      {
        responseString+="<P><Pre>"+e.toString()+"\n"+Tool_Lib_Thin.Get_Stack_Trace(e)+"</Pre>\n";
        e.printStackTrace();        
      }
    }
    finally
    {
      try
      {
//        responseBody.close();
//        if (User_Id!=null && User_Id.equals("Stop_Server")) server.stop(0);
      }
      catch (Exception ex)
      {
        if (!ex.toString().equals("java.io.IOException: Broken pipe"))                   // When user closes a window while half way writing, gets a "Broken pipe"
        {
          ex.printStackTrace();
        }
      }
    }
  }

  public static String Decode_String(String Input)                                       // Fix this problem : // Error : java.lang.IllegalArgumentException: URLDecoder: Illegal hex characters in escape (%) pattern - For input string: "</"
  {
    if (Input==null) return null;                                                        // Replace "+" with "<plus>", and replace "%" with "<percentage>" won't work. Because characters that get encoded have % and + signs in them, 
                                                                                         // so although this helps with % and + characters in a string, yet it doesn't decode things like %20 (space) because you are taking out the percent before decoding.
    String Output="";                                                                    // Stack overflow solution : https://stackoverflow.com/questions/6067673/urldecoder-illegal-hex-characters-in-escape-pattern-for-input-string
    try                                                                                  // A solution is to replace %2B (+) and %25 (%) instead.
    {
      Output=Input.replaceAll("%(?![0-9a-fA-F]{2})","%25");                              // The first replaceAll is the regex that replaces any percent sign that isn't another encoded character with the percent encoded value. The question
      Output=Output.replaceAll("\\+","%2B");                                             // mark makes the proceeding optional, the [0-9a-fA-F] looks for those ranges of characters/numbers and the {2} looks for exactly 2 characters/numbers.
      Output=Output.replaceAll("&amp;","&");                                             // The second replaceAll just replaces the + sign with its encoded value.
      Output=URLDecoder.decode(Output,"utf-8");
    }
    catch (Exception e) { e.printStackTrace(); }
    return Output;
  }

  public LinkedHashMap<String,String> getQueryParameterMap(HttpServletRequest request)
  {
    LinkedHashMap<String,String> queryParameterMap=new LinkedHashMap();
    Map params=request.getParameterMap();
    Iterator i=params.keySet().iterator();
    while (i.hasNext())
    {
      String key=(String)i.next();
      String value=((String[])params.get(key))[0];
      queryParameterMap.put(key,value);
    }
    return queryParameterMap;
  }

  String Get_jQuery()
  {
    return "<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js\"></script>\n"+
           "<script>\n"+
           "$(document).ready(function()\n"+
           "{\n"+
           "  $('button').not('#Save').not('#Login').click($.now(),function(event)\n"+                       // 100% Firefox , IE & Chrome [ OK when click on side if var Clicked_Button=event.target ]
           "   {\n"+
           "     if($(this).attr('id').indexOf('Current_')==0)       // Clicked on Current_Id_Button \n"+
           "     {\n"+
           "       $.get('Test_Servlet?Current_Id_Button='+this.id+'&now='+$.now(),function()\n"+            // use now=$.now() to avoid IE cashing
           "       {\n"+
           "         $.get('Test_Servlet?Action=Get_Pointer_Table&now='+$.now(),function(data)\n"+           // data holds new Pointer_Table html, use now=$.now() to avoid IE cashing
           "         {\n"+                                                                                   // Get_Pointer_Table must be done here after Current_Id_Button to avoid out of sync
           "           var Current_Pointer_Table=data;\n"+
           "           $(\"div.Table\").replaceWith(Current_Pointer_Table);\n"+
           "         });\n"+
           "       });\n"+
           "     }\n"+
//      " alert(data);\n"+
           "   });\n"+
           "});\n"+
           "</script>\n";
  }

  String Get_Pointer_Table(int Id)
  {
    String Pointer_Text="<Font size=4 Color=blue>\u2191</Font><Br><Font size=2 Color=blue>Current</Font>";
    return "    <div class=\"inner Table\">\n"+
           "    <Table border=0>\n"+
           "      <Tr>\n"+
           "        <Td Align=Center Width=82>"+(Id==1?Pointer_Text:"")+"</Td>\n"+
           "        <Td Align=Center Width=82>"+(Id==2?Pointer_Text:"")+"</Td>\n"+
           "        <Td Align=Center Width=82>"+(Id==3?Pointer_Text:"")+"</Td>\n"+
           "        <Td Align=Center Width=82>"+(Id==4?Pointer_Text:"")+"</Td>\n"+
           "        <Td Align=Center Width=82>"+(Id==5?Pointer_Text:"")+"</Td>\n"+
           "        <Td Align=Center Width=82>"+(Id==6?Pointer_Text:"")+"</Td>\n"+
           "        <Td Width=56>&nbsp;</Td>\n"+
           "      </Tr>\n"+
           "    </Table>\n"+
           "    </div>\n";
  }

  String Get_Html_Button(String Id,String Text,int W,int H,int Font_Size)
  {
    return "<button id="+Id+" type=button style=\""+(W<50?"padding: .01em;":"")+"width:"+W+"px;height:"+H+"px;font-size: "+Font_Size+"px\">"+Text+"</button>";
  }

  String Get_Parameters(Map<String,String> params)
  {
    String title="Reading All Request Parameters",paramName,paramValue="";
    String Parameters_Table="<Table Border=1 Align=Center Cellpadding=5 Cellspacing=2>\n  <Tr Bgcolor=#0088FF Colspan=2><Th><Font Color=White>"+title+"</Font></Th></Tr>\n</Table>\n<P>\n"+
                              "<Font Color=blue>This is class [ "+this.getClass().getName()+" ] using the "+requestMethod+" method [ "+new Date()+" ]</Font><P>\n\n"+
                            "<Table Border=1 Align=Center Cellpadding=2 Cellspacing=2>\n  <Tr Bgcolor=#99CCFF><Th>Parameter Name</Th><Th>Parameter Value(s)</Th></Tr>\n";

    for (Map.Entry<String,String> entry : params.entrySet())
    {
      paramName=entry.getKey().replace("+"," ");
      Parameters_Table+="  <Tr><Td Align=Right>"+(paramName.trim().length()<1?"&nbsp;":paramName)+"</Td>";
      try { paramValue=URLDecoder.decode(entry.getValue(),"utf-8"); }
      catch (Exception e) { e.printStackTrace(); }
// Out(paramName+" : "+paramValue);

      Parameters_Table+="<Td>"+(paramValue.trim().length()<1?"&nbsp;":paramValue)+"</Td></Tr>\n";
    }
    Parameters_Table+="</Table>\n";

    return Debug?Parameters_Table:"";
  }

  public LinkedHashMap<String,String> queryToMap(String query)                           // http://localhost:6600/Resume_App?Id=Edit&File_Name=AT&T.txt
  {
//    Out("query = "+query);
    LinkedHashMap<String,String> result=new LinkedHashMap();
    for (String param : query.split("&"))
    {
      String pair[]=param.split("=");
      if (pair.length>1) result.put(pair[0],pair[1]);
      else result.put(pair[0],"");
    }
    return result;
  }

  private static void out(String message)
  {
    System.out.print(message);
    try { System.out.print(message); }
    catch (Exception e) { }
//    GATE_App.Log_TextArea.append(message);
  }

  private static void Out(String message)
  {
    System.out.println(message);
    try { System.out.println(message); }
    catch (Exception e) { }
//    GATE_App.Log_TextArea.append(message+"\n");
  }

  /** Handles the HTTP <code>GET</code> method. This method is called when a form has its tag value method equals to get.
   * @param request servlet request
   * @param response servlet response
   */
  public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException { processRequest(request,response); }

  /** Handles the HTTP <code>POST</code> method. This method is called when a form has its tag value method equals to post.
   * @param request servlet request
   * @param response servlet response
   */
  public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException { processRequest(request,response); }

  /** This method is called when a HTTP put request is received.
   * 
   * @param request the request send by the client to the server
   * @param response the response send by the server to the client
   */
  public void doPut(HttpServletRequest request, HttpServletResponse response)   throws ServletException,IOException
  {
        // Put your code here
  }

  /** This method is called when a HTTP delete request is received.
   * 
   * @param request the request send by the client to the server
   * @param response the response send by the server to the client
   */
  public void doDelete(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException
  {
        // Put your code here
  }

  public void destroy() { super.destroy(); }

  /**
   * Returns information about the servlet, such as 
   * author, version, and copyright. 
   *
   * @return String information about this servlet
   */
  public String getServletInfo() { return "This is servlet : [ "+this.getClass().getName()+" ]"; }

  /**
   * Initialization of the servlet. <br>
   *
   * @throws ServletException if an error occurs
   */
  public void init() throws ServletException
  {
        // Put your code here
  }
}

================================================== =========

package Utility;

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import javax.servlet.http.HttpSession;
import java.util.List;
import java.util.ArrayList;

public class Session_Counter implements HttpSessionListener
{
  private List<String> sessions=new ArrayList<>();
  public static final String COUNTER="session-counter";
  GATE_4_App_Lib GATE_4_app_lib=new GATE_4_App_Lib();

  public void sessionCreated(HttpSessionEvent event)
  {
    System.out.println("Session_Counter.sessionCreated");
    HttpSession session=event.getSession();
    sessions.add(session.getId());
    session.setAttribute(Session_Counter.COUNTER,this);
  }

  public void sessionDestroyed(HttpSessionEvent event)
  {
    System.out.println("Session_Counter.sessionDestroyed");
    HttpSession session=event.getSession();
    sessions.remove(session.getId());
    session.setAttribute(Session_Counter.COUNTER,this);
    GATE_4_app_lib.Save_To_GATE_Web_Log("[-] Client_IP = "+session.getAttribute("Client_IP")+", Client_Browser = "+session.getAttribute("Client_Browser"));
  }

  public int getActiveSessionNumber() { return sessions.size(); }
}

最佳答案

是的,好像nginx配置不正确

curl -vvv http://gatecybertech.net/Test_Servlet

<skip>
Set-Cookie: JSESSIONID=E3551B683A0FD1A8A17829022A070AE2;path=/GATE_Web;HttpOnly

您的站点使用路径 /GATE_Web 设置 cookie,但从浏览器的角度来看,URL 不在该路径下,因此浏览器不会在后续请求中发送 cookie,并且 HTTP session 将被终止。重新开始。

一个建议是也映射到 nginx 中的 /GATE_Web 并使用 http://gatecybertech.net/GATE_Web/Test_Servlet 而不是 http:///gatecybertech.net/Test_Servlet

关于Java servlet session 无法与 NGinx 正常工作,如何修复?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48269262/

相关文章:

java - 输入/输出Java

java - Java Swing 中带有自定义事件的接口(interface)之后的 .class

javascript - 将数据从 HTML5 存储存储到应用程序数据库面临困难

c# - 使用 Master Code Behind 的内容页面

javascript - Facebook Bigpipe,做得对还是不对?

java - 有没有办法将对象添加到 JComboBox 并分配一个要显示的字符串?

java - 将多个图像合并为单个文件

Laravel 5.6 - session 过期后不会持续存在

java - 在 webapp 之间共享对象时出现 ClassCastError

java - 出现 "java.net.ProtocolException: Server redirected too many times"错误