CORS 使用ajax+servlet实现
主要是针对非IE的CORS实现,因为IE的CORS直接使用XDomainRequest,比较简单,功能也比较简单。在此是针对非IE中如何实现跨源。 主要有两个方面:1.如何使用PreflightRequest实现功能较丰富跨域请求,功能丰富体现在:可以发送自定义头部信息;可以使用get和post以外的方法;可以发送不同类型的主体内容。摘录一段文档: Unlike simple requests(discussed above),"preflighted" requests first send an HTTP request by the GET,HEAD orPOST . Also,ifis used to send request data with a Content-Type application/x-www-form-urlencoded,multipart/form-data text/plainrequest sends an XML payload to the server usingapplication/xml text/xmlispreflighted.(2)It sets custom headers in the request (e.g. the request uses a header such asx-zd) Note:Starting inGecko2.0,the (参考资料:https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS?redirectlocale=en-US&redirectslug=HTTP_access_control) 源码实例:js部分: function crosFunc(){
var xhr=new XMLHttpRequest();
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr.status>=200&&xhr.status<=300||xhr.status==304){
console.log("--->"+xhr.getAllResponseHeaders());//为空,不能访问返回的头信息
console.log(xhr.responseText);
console.log(console.log(document.cookie));//username=444 undefined 因为同源策略的影响,访问不到从服务器返回来的cookie
}
else{
alert("cros failed!");
}
}
}
if('withCredentials' in xhr){//检测xhr是否支持CORS,如果不支持,说明是ie,就只能使用XDomainRequest进行跨域
console.log("it is true");
}
xhr.open('get','http://202.197.66.228:8083/TestCORS/ServerServlet',true);
xhr.setRequestHeader('x-zd','zd');//发送自定义头部
xhr.send(null);
}
crosFunc();
</script>
servlet部分:注意红色部分的代码,要在doOptions中加入一些头信息,这样浏览器才会把结果交给js,否则就会出错
public class ServerServlet extends HttpServlet { public ServerServlet() { super(); } public void destroy() { super.destroy(); // Just puts "destroy" string in log // Put your code here } public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException { this.execute(request,response); } public void doPost(HttpServletRequest request,response); } private void execute(HttpServletRequest request,HttpServletResponse resp){ resp.setCharacterEncoding("utf-8"); Cookie [] cs=request.getCookies(); System.out.println("cookies:"+( cs==null?0:cs.length)); Cookie c=new Cookie("tongguo","true"); resp.addCookie(c); resp.addHeader("Access-Control-Allow-Origin","http://localhost:8083");//注意此处 List<UserInfo> tempt=_getSomeInfos(); JSONObject jobj=new JSONObject(); jobj.put("rows",tempt); System.out.println(jobj); byte[] jsonBytes; try { jsonBytes = jobj.toString().getBytes("utf-8"); resp.setContentLength(jsonBytes.length); resp.getOutputStream().write(jsonBytes); resp.getOutputStream().flush(); resp.getOutputStream().close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override protected void doOptions(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException { resp.addHeader("Access-Control-Allow-Origin","http://localhost:8083"); resp.addHeader("Access-Control-Max-Age","1728000"); resp.addHeader("Access-Control-Allow-Methods","GET,POST,OPTIONS"); resp.addHeader("Access-Control-Allow-Headers","User-Agent,Origin,Cache-Control,Content-type,x-zd,Date,Server,withCredentials"); //注意此处不要再调用super.dooptions方法 } private List<UserInfo> _getSomeInfos() { List<UserInfo> result=new ArrayList<UserInfo>(); UserInfo u=null; for(int i=0;i<30;i++){ u=new UserInfo(); u.setUsername("zhang"+i); if(i%2==0){ u.setSex("Female"); u.setAddress("四川"); u.setSchool("CSU"); }else{ u.setSex("Male"); u.setAddress("湖南长沙"); u.setSchool("CWNU"); } result.add(u); } Collection nuCon = new Vector(); nuCon.add(null); result.removeAll(nuCon); return result; } } 结果:发出了两次请求。第一次是options请求,第二次是get请求。
2.是使用CORS,发送一些带凭据的跨域请求,所谓的凭据就是一些cookie,HTTP认证什么的。摘录一段文档: The most interesting capability exposed by both 一般默认情况下都是不启用带有凭据的跨域,因此如果想要启用的话,只需将XMLHttpRequest的withCredentials属性设置为True,注意此处从服务器返回来的cookie信息以及响应头信息,可以通过浏览器显示出来,但是在js中不能用代码进行访问。 js代码:
<script type="text/javascript"> function crosFunc(){ var xhr=new XMLHttpRequest(); xhr.onreadystatechange=function(){ if(xhr.readyState==4){ if(xhr.status>=200&&xhr.status<=300||xhr.status==304){ console.log("--->"+xhr.getAllResponseHeaders());//为空,不能访问返回的头信息 console.log(xhr.responseText); console.log(console.log(document.cookie));//username=444 undefined 因为同源策略的影响,访问不到从服务器返回来的cookie } else{ alert("cros failed!"); } } } if('withCredentials' in xhr){//检测xhr是否支持CORS,如果不支持,说明是ie,就只能使用XDomainRequest进行跨域 console.log("it is true"); } xhr.open('get',true); setCookie("username","444",12); xhr.setRequestHeader('x-zd','zd'); xhr.withCredentials = "true";//向服务器说明我要发送带凭据的请求 xhr.send(null); } crosFunc(); function setCookie(key,value,hour){ var _cookie=key+"="+encodeURIComponent(value); if(hour>0){ var date=new Date(); date.setTime(date.getTime()+hour*3600*1000); _cookie+=";expires="+date.toGMTString(); } document.cookie=_cookie; } java代码,只是在doOptions和execute方法中各加入了同一行代码: resp.addHeader("Access-Control-Allow-Credentials","true"); 结果:也是发出了两个请求,options请求和上面的一样,只看get请求:
刷新该页面,可以发现,发出带有cookie的请求: 同时在控制台查看响应的头部,主体内容,和cookie信息:
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |