重要不要删除,花了好久才解決
重要不要删除,花了好久才解決
重要不要删除,花了好久才解決
報錯:
Access to XMLHttpRequest at 'http://localhost:8080/SpringBootServer/testfile' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
-
誘因
兩天研究springboot,因為剛接觸沒多久springboot,是以遇到了一堆的問題,首先這個springboot我這裡建立的是沒有web.xml配置檔案的,是以在設定過濾器的時候,不知道在哪裡設定,導緻網上查的一堆在web.xml通過filter設定的過濾器解決跨域問題,我這裡都沒有用,還有寫一寫配置檔案或者是寫一個類檔案,配置檔案沒有,類檔案沒有用。于是我找了一個晚上,終于找到了解決的辦法以及原因,詳細如下。
- 前台的代碼塊如下
賬号:
密碼: 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
- 背景代碼塊如下,注:這個是springboot項目
package cn.test.controller;import cn.test.pojo.SmbmsRole;import cn.test.pojo.SmbmsUser;import cn.test.service.UserService;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.util.Date;import java.util.List;/** * @RestController 聲明這個是個controller并且傳回的資料類型可以為json * @CrossOrigin springboot中支援跨域的注解 * */@[email protected] class UserController {/** * @Resource 自動注入的注解 * */ @Resource private StringRedisTemplate stringRedisTemplate; @Resource private UserService userService; /** * 進行登入驗證的方法 * 接受ajax傳遞過來的參數 * 這裡還需要session,response,request來進行一些跨域的設定 * 親測,最終成功運作并且結果傳回為true * */ @RequestMapping("/doLogin") public String doLogin(@RequestParam("userCode")String userCode, @RequestParam("userPassword")String userPassword, HttpSession session, HttpServletResponse response, HttpServletRequest request){ /** * 測試的輸出一下發送請求的域名 * 最主要的解決問題的代碼來了,我這裡為了盡量闡述明白查閱了好多資料,寫了大量的注釋,希望大家可以看的更明白一點 * */ System.out.println(request.getHeader("Origin")); /** *在響應 header 中設定 ‘*’ 來允許來自所有域的跨域請求通路 * 較靈活的設定方式 允許這個域名進行通路,request.getHeader("Origin"),通過request.getHeader('Origin')來得到通路來源的域名 * 這行代碼很重要,必須寫 * */ response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")); /** * 首部字段 Access-Control-Allow-Headers 表明伺服器允許請求中攜帶字段 X-PINGOTHER 與 Content-Type。 * Access-Control-Allow-Headers 的值為逗号分割的清單 * 這個可以不寫,寫這個就是表明伺服器允許請求中攜帶的字段 * */ response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); /** * 前台ajax發送的請求中對應用戶端的 xhrFields.withCredentials: true 參數 * 伺服器端通過在響應 header 中設定 Access-Control-Allow-Credentials = true 來運作用戶端攜帶證書式通路。 * 通過對 Credentials 參數的設定,就可以保持跨域 Ajax 時的 Cookie。這裡需要注意的是: * 伺服器端 Access-Control-Allow-Credentials = true時,參數Access-Control-Allow-Origin 的值不能為 '*' * 這是因為請求的首部中攜帶了 Cookie 資訊 * 如果伺服器端的響應中未攜帶 Access-Control-Allow-Credentials: true ,浏覽器将不會把響應内容傳回給請求的發送者。 * 這行代碼也必須加 * */ response.setHeader("Access-Control-Allow-Credentials", "true"); System.out.println(session.getId()); System.out.println("進入了登入驗證的方法"); SmbmsUser smbmsUser = userService.getUser(userCode,userPassword); session.setAttribute("smbmsUser",smbmsUser); if(smbmsUser!=null){ return "true"; }else{ return "false"; } } /** * 增加資料的控制層方法 * 這裡也需要使用到session,response來進行一系列的設定 * */ @RequestMapping(value = "/add",method = RequestMethod.POST) public Object addSmbmsRole( SmbmsRole smbmsRole,HttpSession session,HttpServletResponse response, HttpServletRequest request){ response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")); response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); response.setHeader("Access-Control-Allow-Credentials", "true"); System.out.println("進入增加資料的方法"); System.out.println(session.getId()); System.out.println(((SmbmsUser)session.getAttribute("smbmsUser")).getCreatedBy()); smbmsRole.setCreatedBy(((SmbmsUser)session.getAttribute("smbmsUser")).getCreatedBy()); smbmsRole.setCreationDate(new Date()); int count = userService.addSmbmsRole(smbmsRole); if(count>0){ return "true"; }else{ return"false"; } }}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
-
測試過程以及一些注意事項
首先,前端的ajax發送請求時
crossDomain: true,1
這行代碼可以忽略,對結果沒有什麼較大的影響。
在前台進行設定的時候我還找見一個需要在上面加上以下代碼來進行處理,但是對我沒有用,你們可以試試
1
測試注掉crossDomain: true,對運作不影響,
測試注掉xhrFields: {withCredentials: true},得到的兩個Cookie的ID不一緻,出現了問題,是以xhrFields: {withCredentials: true},必備
測試背景隻寫
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));1
運作結果進入方法體,但是傳回的時候不會進入success方法,進入error方法并且頁面報錯資訊如下
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5CMhZ2NxIGZ3QmM5YWM2MWM4MjN1UDZhdDN1MWYxIDO08CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
背景測試隻寫
response.setHeader("Access-Control-Allow-Credentials", "true");1
運作結果進入方法體,但是傳回的時候不會進入success方法,進入error方法并且頁面報錯資訊如下
背景隻寫
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");1
會進入背景的方法體,頁面都會報錯并且彈出error彈窗
測試背景寫全
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");response.setHeader("Access-Control-Allow-Credentials", "true");123
成功進入方法體,結果成功傳回,進入success方法并彈出傳回的結果,成功的跳轉頁面
測試隻寫其中的兩個,除了隻寫這兩行代碼的時候執行成功,其他兩種組合方式都以失敗告終
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));response.setHeader("Access-Control-Allow-Credentials", "true");12
詳細的原因都在代碼塊的備注中寫的很詳細了,如果有還不是很懂的可以看下面的連結位址
最終簡述一下解決ajax發送跨域的請求的辦法
ajax中加入一行代碼如下(有的人加上這一句代碼背景不用設定就可以,但是我不可以)
xhrFields: {withCredentials: true},1
Controller的方法體内加入如下兩行代碼
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));response.setHeader("Access-Control-Allow-Credentials", "true");12
問題成功的解決!
順便說一下,在你需要對session操作的方法體内和ajax請求,如果ajax加了攜帶Cookie的代碼,背景的方法體内沒有加上那兩行代碼的話,可以對資料進行操作,但是return的時候不會正确的進入到success的方法體内,一直會進入到error的方法。但是值盡然操作成功了,而且還是同一個Cookie,這個問題目前未知,背景加上那兩行代碼的時候,就一切正常了。
問題,為什麼我在登入的時候已經攜帶了Cookie過去,在其他的ajax請求的時候我也都攜帶了Cookie,那麼為什麼我在對Cookie的資料進行操作的時候沒有任何問題,但是值确不能正确的傳回到前台,無法進入success?
剛才測試的時候又出現的一個新的問題,哎,頭疼,腦子已經糊了。
我當時解決問題的參考資料:https://blog.csdn.net/cckevincyh/article/details/81140443
進階資料:https://blog.csdn.net/wzl002/article/details/51441704
進行配置詳細解釋的進階資料:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS#功能概述
強力推薦研究觀看兩個進階資料,看了一遍以後雖說不是能瞬間醒悟但是這個資料裡面對一些跨域HTTP(CORS)講解的非常到位,其實搞了半天才解決的原因還是技術太淺了,綜上所述其實前台ajax就一行代碼就可以解決,背景的Controller隻需要兩行代碼就可以,就這麼三行代碼,但是我搞了一個晚上才解決,心累啊,找到了解決辦法的那一刻,我突然有種想哭的感覺…希望有人看到了之後可以一起研究學習,也希望能給你們提供到幫助!
好了,問題解決了,欣賞一下小姐姐,放松一下吧