1. 程式人生 > >避免使用查詢引數在瀏覽器位址列暴露敏感資訊

避免使用查詢引數在瀏覽器位址列暴露敏感資訊

通常在登入系統時會傳遞使用者名稱、密碼到伺服器,伺服器接收到資料驗證通過後,再重定向到主頁面。比如下面的返回引數就重定向到index對映的方法:

return "redirect:/index.action?loginId="
               + URLEncoder.encode(loginId, "utf-8")+"&userName="+URLEncoder.encode(userName, "utf-8");

因為是重定向方法,所以在index對映的方法中需要新增引數接收使用者資訊,不能通過ModelMap獲取,因為不是同一個請求,ModelMap會被清空,無法獲取資料。然後在重定向方法中返回檢視名稱,這樣瀏覽器顯示的路徑就類似http://localhost:8080/test/index.action?loginId=xxx&userName=xxx,這樣就會把使用者Id和使用者暱稱暴露出來。

因此我們需要一種方法將這些資訊隱藏,然後在重新整理瀏覽器時,後臺仍然可以獲取到這些資訊。

這個方法就是通過org.springframework.web.servlet.mvc.support.RedirectAttributes介面傳遞引數,這樣查詢引數也不會在瀏覽器位址列暴露,並且在重定向時可以將資料傳遞到ModelMap中。只不過不需要我們自行管理session中的資料量,比較方便。實現方式就是,在重定向之前將上一個請求的ModelMap中的資料儲存到RedirectAttributes中,然後通過session傳遞到下一個請求,然後RedirectAttributes中的資料會傳遞到下一個請求的ModelMap中。

redirectAttributes.addFlashAttribute("loginId",URLEncoder.encode(loginId, "utf-8"));
redirectAttributes.addFlashAttribute("userName",URLEncoder.encode(userName, "utf-8"));
return "redirect:/index.action";

這樣瀏覽器位址列顯示的就是http://localhost:8080/test/index.action,我們重新整理瀏覽器請求index.action對映的方法時,因為不能像之前一樣通過查詢引數傳遞請求引數,而且Model這時就會清空,但session中還是可以獲取到之前的資料,因此不影響重新整理頁面。Spring MVC包版本必須是3.1及以上才行:

http://www.springframework.org/schema/mvc  
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd

需要注意的是使用RedirectAttributes需要在spring配置中增加一個配置:

<!-- 啟用springmvc -->
<mvc:annotation-driven />

否則會報下面的錯誤:

java.lang.IllegalStateException: Argument [RedirectAttributes] is of type Model or Map but is not assignable from the actual model. You may need to switch newer MVC infrastructure classes to use this argument.
	at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:330)
	at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
	at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:440)
	at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:428)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
	at com.jshx.fileManager.filter.FileFileter.doFilter(FileFileter.java:40)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
	at org.springframework.orm.hibernate4.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:151)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:509)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1104)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:684)
	at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2508)
	at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2497)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:744)

參考書籍:《Spring 實戰(第4版)》