我有一个运行 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=" ",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("&","&"); // 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> </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?" ":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?" ":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/