近一段時間項目問題總結
關于關于AJAX 跨域請求web項目/ajax跨域session問題,在這裡經常存在的問題總結一下
跨域:
什麼
是跨域?
跨域,指的是浏覽器不能執行其他網站的腳本。它是由浏覽器的同源政策造成的,是浏覽器對javascript施加的安全限制。
所謂同源是指,域名,協定,端口均相同,不明白沒關系,舉個栗子:
http://www.123.com/index.html 調用 http://www.123.com/server.php (非跨域)
http://www.123.com/index.html 調用 http://www.456.com/server.php (主域名不同:123/456,跨域)
http://abc.123.com/index.html 調用 http://def.123.com/server.php (子域名不同:abc/def,跨域)
http://www.123.com:8080/index.html 調用 http://www.123.com:8081/server.php (端口不同:8080/8081,跨域)
http://www.123.com/index.html 調用 https://www.123.com/server.php (協定不同:http/https,跨域)
請注意:localhost和127.0.0.1雖然都指向本機,但也屬于跨域。浏覽器執行javascript腳本時,會檢查這個腳本屬于哪個頁面,如果不是同源頁面,就不會被執行。
一、CORS概述
跨源資源共享标準通過新增一系列 HTTP 頭,讓伺服器能聲明那些來源可以通過浏覽器通路該伺服器上的各類資源(包括CSS、圖檔、JavaScript 腳本以及其它類資源)。另外,對那些會對伺服器資料造成破壞性影響的 HTTP 請求方法(特别是 GET 以外的 HTTP 方法,或者搭配某些MIME類型的POST請求),标準強烈要求浏覽器必須先以 OPTIONS 請求方式發送一個預請求(preflight request),進而獲知伺服器端對跨源請求所支援 HTTP 方法。在确認伺服器允許該跨源請求的情況下,以實際的 HTTP 請求方法發送那個真正的請求。伺服器端也可以通知用戶端,是不是需要随同請求一起發送信用資訊(包括 Cookies 和 HTTP 認證相關資料)。
二、CORS原理
例如:域名A(http://a.example)的某 Web 應用程式中通過<img>标簽引入了域名B(http://b.foo)站點的某圖檔資源(http://b.foo/image.jpg)。這就是一個跨域請求,請求http報頭包含Origin: http://a.example,如果傳回的http報頭包含響應頭 Access-Control-Allow-Origin: http://a.example (或者Access-Control-Allow-Origin: http://a.example),表示域名B接受域名B下的請求,那麼這個圖檔就運作被加載。否則表示拒絕接受請求。
三、CORS跨域請求控制方法
1.http請求頭
Origin: 普通的HTTP請求也會帶有,在CORS中專門作為Origin資訊供後端比對,表明來源域。
Access-Control-Request-Method: 接下來請求的方法,例如PUT, DELETE等等
Access-Control-Request-Headers: 自定義的頭部,所有用setRequestHeader方法設定的頭部都将會以逗号隔開的形式包含在這個頭中
2.http響應頭
然後浏覽器再根據伺服器的傳回值判斷是否發送非簡單請求。簡單請求前面講過是直接發送,隻是多加一個origin字段表明跨域請求的來源。然後伺服器處理完請求之後,會再傳回結果中加上如下控制字段
Access-Control-Allow-Origin: 允許跨域通路的域,可以是一個域的清單,也可以是通配符"*"。這裡要注意Origin規則隻對域名有效,并不會對子目錄有效。即http://foo.example/subdir/ 是無效的。但是不同子域名需要分開設定,這裡的規則可以參照同源政策
Access-Control-Allow-Credentials: 是否允許請求帶有驗證資訊,
Access-Control-Expose-Headers: 允許腳本通路的傳回頭,請求成功後,腳本可以在
Access-Control-Max-Age: 緩存此次請求的秒數。在這個時間範圍内,所有同類型的請求都将不再發送預檢請求而是直接使用此次傳回的頭作為判斷依據,非常有用,大幅優化請求次數
Access-Control-Allow-Methods: 允許使用的請求方法,以逗号隔開
Access-Control-Allow-Headers: 允許自定義的頭部,以逗号隔開,大小寫不敏感
如果程式猿偷懶将Access-Control-Allow-Origin設定為:Access-Control-Allow-Origin: * 允許任何來自任意域的跨域請求,那麼久存在被 DDoS攻擊的可能。
SSM項目解決辦法:
在maven或者lib中加入cors-filter-1.7.jar,java-property-utils-1.9.jar 這兩個包 WEB.XML中:
<filter>
<filter-name>CORS</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
<init-param>
<param-name>cors.allowOrigin</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.supportedMethods</param-name>
<param-value>GET, POST, HEAD, PUT, DELETE</param-value>
</init-param>
<init-param>
<param-name>cors.supportedHeaders</param-name>
<param-value>Accept, Origin, X-Requested-With, Content-Type, Last-Modified</param-value>
</init-param>
<init-param>
<param-name>cors.exposedHeaders</param-name>
<param-value>Set-Cookie</param-value>
</init-param>
<init-param>
<param-name>cors.supportsCredentials</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CORS</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
這裡有坑請注意。如果不小心配置成了 <filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern> </filter-mapping> 不但不安全而且此時的SESSION不可用,每次請求都是一個新的Session 是以要避免此種配置 HTML頁面中的寫法
var da={phone:"18240449832",username:"111",userpass:"111",random:"666666"}
$.ajax({
type:"POST",
url:"http://192.168.2.102:6060/loginUser", //通過原有密碼設定新密碼
dataType:"json",
data:JSON.stringify(da),
xhrFields: {
withCredentials: true
},
//crossDomain: true,
contentType:"application/json; charset=utf-8",
success : function(result) {
console.log(result);
}
});
});
此時的跨域可以實作session統一
方法二 自己寫的 filter類,自己在在業務項目中配置web.xml 中配置想要的xml 檔案。
如:java類filter:
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
- ServletException {
- // TODO Auto-generated method stub
- HttpServletResponse res = (HttpServletResponse) response;
- res.setContentType("text/html;charset=UTF-8");
- res.setHeader("Access-Control-Allow-Origin", "*");
- res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
- res.setHeader("Access-Control-Max-Age", "0");
- res.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token");
- res.setHeader("Access-Control-Allow-Credentials", "true");
- res.setHeader("XDomainRequestAllowed","1");
- chain.doFilter(request, response);
- }
- web.xml配置:
-
- <filter>
- <filter-name>cors</filter-name>
- <filter-class>com.aima.CorsFilter</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>cors</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- springboot中解決跨域并且session統一的配置
-
@Configuration
public class CorsConfig extends WebMvcConfigurerAdapter {
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "DELETE", "PUT")
.maxAge(3600);
}
}
- 以上就是跨域的一些總結,有的地方配置的也不夠仔細,如有問題,請各位指教!