Java servlet会话无法与NGinx正常工作,如何修复?
我有一个运行Java servlet的站点,使用tomcat8.5,运行良好: 但是ISP的家伙担心安全问题,所以他建议我们使用NGinx使其更安全,因此同一个应用程序正在执行NGinx代理传递,并且运行在: 它运行不正常,当我点击按钮时,底部的光标没有移动,我注意到页面右上角的“用户数:”正在快速增加,即使只有一个用户[me]在测试应用程序。我使用Java会话来跟踪新用户会话,它在第一个站点中运行良好,但在使用NGinx时,它的行为不正确 由于该应用程序很复杂,为了快速找出为什么它不能与NGinx正常工作,我简化了该应用程序,并创建了另一个名为Test_servlet的servlet: 如您所见,当您单击不同的按钮时,带有follow的光标将指向已单击的按钮 与NGinx一起运行的相同测试\u Servlet位于: 使用此按钮,光标将不会跟随您单击的按钮 我怀疑NGinx的配置没有正确设置,您认为它有什么问题 这里是简化的servletJava servlet会话无法与NGinx正常工作,如何修复?,java,session,servlets,nginx,Java,Session,Servlets,Nginx,我有一个运行Java servlet的站点,使用tomcat8.5,运行良好: 但是ISP的家伙担心安全问题,所以他建议我们使用NGinx使其更安全,因此同一个应用程序正在执行NGinx代理传递,并且运行在: 它运行不正常,当我点击按钮时,底部的光标没有移动,我注意到页面右上角的“用户数:”正在快速增加,即使只有一个用户[me]在测试应用程序。我使用Java会话来跟踪新用户会话,它在第一个站点中运行良好,但在使用NGinx时,它的行为不正确 由于该应用程序很复杂,为了快速找出为什么它不能与NGi
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
}
}
\n”;
e、 printStackTrace();
}
}
最后
{
尝试
{
//responseBody.close();
//如果(User_Id!=null&&User_Id.equals(“Stop_Server”))Server.Stop(0);
}
捕获(例外情况除外)
{
如果(!ex.toString().equals(“java.io.IOException:breaked pipe”)//当用户在写入中途关闭窗口时,会得到一个“breaked pipe”
{
例如printStackTrace();
}
}
}
}
public static String Decode_String(String Input)//修复此问题://Error:java.lang.IllegalArgumentException:urldecker:escape(%)模式中的非法十六进制字符-对于输入字符串:“是,nginx配置似乎不正确
curl -vvv http://gatecybertech.net/Test_Servlet
<skip>
Set-Cookie: JSESSIONID=E3551B683A0FD1A8A17829022A070AE2;path=/GATE_Web;HttpOnly
curl-vvvhttp://gatecybertech.net/Test_Servlet
设置Cookie:JSESSIONID=E3551B683A0FD1A8A17829022A070AE2;路径=/GATE\u Web;HttpOnly
您的站点将cookie设置为路径/GATE\u Web
,而从浏览器的角度看,URL不在此路径下,因此浏览器不会在后续请求中发送cookie,HTTP会话将重新启动
一个建议是在nginx中映射到
/GATE\u Web
,并使用http://gatecybertech.net/GATE_Web/Test_Servlet
而不是http://gatecybertech.net/Test_Servlet
好的,我已经解决了这个问题。通过执行以下操作:
在/opt/tomcat85/conf/context.xml中,将“
”更改为:
...
你能显示nginx位置吗?非常有用的信息,我的ISP告诉我:“网络服务器(nginx)配置符合代理传递tomcat的确切要求。请参阅以下参考资料,并确保您的webapp符合要点底部的根目录要求:然后他给我发送了以下消息:为Apache tomcat 7配置Nginx…同样重要的是,我们的Java web应用程序位于根目录中,而不是。我们可以通过在标记内向server.xml文件添加一个节,可以轻松地完成此操作。重新启动Tomcat,然后在最后通过端口80启动Nginx。那么我的网站如何使用路径“/”而不是“/GATE\u Web”设置cookie,我在哪里设置?
curl -vvv http://gatecybertech.net/Test_Servlet
<skip>
Set-Cookie: JSESSIONID=E3551B683A0FD1A8A17829022A070AE2;path=/GATE_Web;HttpOnly
<Context sessionCookiePath="/">
...
</Context>