1. 程式人生 > >SpringMvc+ajax跨域請求時,出現options型別的請求並返回403的解決方案

SpringMvc+ajax跨域請求時,出現options型別的請求並返回403的解決方案

在使用

[javascript] view plain copy
  1. $.ajax({  
  2.         url:'http://127.0.0.1:8081/rest/ccxxx/xxxx',  
  3.         type:'POST',  
  4.         dataType:"json",  
  5.         contentType:"application/json",  
  6.         data:JSON.stringify({wechatId:1}),  
  7.         crossDomain:true,  
  8.         async:false,  
  9.         cache:false
    ,  
  10.         success:function(data){  
  11.         },  
  12.         error:function(data){  
  13.         }  
  14.     });  
  15. }  
請求時,瀏覽器返回了以options格式請求服務端403的錯誤。

查閱資料得知,

當contentType設定為三個常用的格式以外的格式,如“application/json”時,會先發送一個試探的OPTIONS型別的請求給服務端。在這時,單純的在業務介面response新增Access-Control-Allow-Origin 由於還沒有走到所以不會起作用。

解決方案:

在服務端增加一個攔截器

用於處理所有請求並加上允許跨域的頭

  1. CommonInterceptor.java  
  1. /**  
  2.  * 請求攔截器,處理跨域問題  
  3.  * @author huangjinkai  
  4.  *  
  5.  */  
  6. public class CommonInterceptor implements HandlerInterceptor {  
  7.     private List<String> excludedUrls;  
  8.     public List<String> getExcludedUrls() {  
  9.         return excludedUrls;  
  10.     }  
  11.     public void setExcludedUrls(List<String> excludedUrls) {  
  12.         this.excludedUrls = excludedUrls;  
  13.     }  
  14.     /**  
  15.      *   
  16.      * 在業務處理器處理請求之前被呼叫 如果返回false   
  17.      * 從當前的攔截器往回執行所有攔截器的afterCompletion(),  
  18.      * 再退出攔截器鏈, 如果返回true 執行下一個攔截器,  
  19.      * 直到所有的攔截器都執行完畢 再執行被攔截的Controller  
  20.      * 然後進入攔截器鏈,  
  21.      * 從最後一個攔截器往回執行所有的postHandle()  
  22.      * 接著再從最後一個攔截器往回執行所有的afterCompletion()  
  23.      *   
  24.      * @param  request  
  25.      *   
  26.      * @param  response  
  27.      */  
  28.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response,  
  29.             Object handler) throws Exception {  
  30.         response.setHeader("Access-Control-Allow-Origin", "*");  
  31.         response.setHeader("Access-Control-Allow-Methods", "*");  
  32.         response.setHeader("Access-Control-Max-Age", "3600");  
  33.         response.setHeader("Access-Control-Allow-Headers",  
  34.                 "Origin, X-Requested-With, Content-Type, Accept");  
  35.         return true;  
  36.     }  
  37.     // 在業務處理器處理請求執行完成後,生成檢視之前執行的動作  
  38.     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,  
  39.             ModelAndView modelAndView) throws Exception {  
  40.     }  
  41.     /**  
  42.      *   
  43.      * 在DispatcherServlet完全處理完請求後被呼叫  
  44.      * 當有攔截器丟擲異常時,  
  45.      * 會從當前攔截器往回執行所有的攔截器的afterCompletion()  
  46.      *   
  47.      * @param request  
  48.      *   
  49.      * @param response  
  50.      *   
  51.      * @param handler  
  52.      *   
  53.      */  
  54.     public void afterCompletion(HttpServletRequest request, HttpServletResponse response,  
  55.             Object handler, Exception ex) throws Exception {  
  56.     }  
  57. }  

applicationContext.xml

  1. <mvc:interceptors>
  2.           <mvc:interceptor>
  3.           <mvc:mappingpath="/**"/>
  4.           <beanclass="com.xxx.ccc.vvv.CommonInterceptor">
  5.           <propertyname="excludedUrls">
  6.            <list>
  7.                <value>/</value>
  8.            </list>
  9.           </property>
  10.           </bean>
  11.        </mvc:interceptor>
  12.    </mvc:interceptors>


攔截器程式碼參考
http://blog.csdn.net/u013292160/article/details/51769374

配置完成後重啟伺服器再次請求就可以看到瀏覽器會發送兩個請求 並且均為200OK