我用webstrome取访问我的工程(localhost:8080)为什么这里算是跨域呢,因为webstrom的端口和8080不一致,下面是我的(端口号63342)我另一位同学是63343,可见webstrom是用了你8080外另一个端口的。
而且这个端口号可以修改:
jsonp解决:
https://blog.csdn.net/hansexploration/article/details/80314948
我前端的请求:
$.ajax({
url: 'http://localhost:8080/nydl/func/testCrossOriginFeng',
// url: 'http://localhost:8080/nydl/func/web/testCrossOrigin',
type: 'post',
dataType: 'json',
data: '{"user": "fengUser"}',
crossDomain: true,
contentType: 'application/json', //必须写这个,否则前后端contenttype不一致,前端默认application/x-www-form-urlencoded; charset=UTF-8,后端text/html;charset=utf-8。
// 而只要前端设置了application/json格式,后端在没有明确设置时,也能变成application/json
success: callback,
error:function(XMLHttpRequest, textStatus, errorThrown) {
alert(XMLHttpRequest.readyState);
alert(XMLHttpRequest.status);
alert(textStatus);
}
});
function callback(result) {
alert("success");
console.log(result.data.number);
$('#content').html(result.data.number);
}
后端代码:
参考:超详细 Spring @RequestMapping 注解使用技巧 https://www.iteye.com/news/32657/
用 @RequestMapping 处理 HTTP 的各种方法
Spring MVC 的 @RequestMapping 注解能够处理 HTTP 请求的方法, 比如 GET, PUT, POST, DELETE 以及 PATCH。 所有的请求默认都会是 HTTP GET 类型的。 为了能将一个请求映射到一个特定的 HTTP 方法,你需要在 @RequestMapping 中使用 method 来声明 HTTP 请求所使用的方法类型,如下所示:@RestController
@RequestMapping("/home")
public class IndexController {
@RequestMapping(method = RequestMethod.GET)
String get() {
return "Hello from get";
}
@RequestMapping(method = RequestMethod.DELETE)
String delete() {
return "Hello from delete";
}
@RequestMapping(method = RequestMethod.POST)
String post() {
return "Hello from post";
}
@RequestMapping(method = RequestMethod.PUT)
String put() {
return "Hello from put";
}
@RequestMapping(method = RequestMethod.PATCH)
String patch() {
return "Hello from patch";
}
}
在上述这段代码中, @RequestMapping 注解中的 method 元素声明了 HTTP 请求的 HTTP 方法的类型。 所有的处理处理方法会处理从这同一个 URL( /home)进来的请求, 但要看指定的 HTTP 方法是什么来决定用哪个方法来处理。
例如,一个 POST 类型的请求 /home 会交给 post() 方法来处理,而一个 DELETE 类型的请求 /home 则会由 delete() 方法来处理。 你会看到 Spring MVC 将使用这样相同的逻辑来映射其它的方法。
我的代码:
package cn.edu.sdu.nydl.bean.web;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import cn.edu.sdu.common.util.CommonTool;
@RestController
@RequestMapping(value = "/crossOrigin")
public class CrossOrigionTest{
@RequestMapping(method = RequestMethod.POST)
public Map testCrossOriginPost(HttpServletRequest httpRequest,@RequestBody Object obj) {
Map request = (Map) obj;
String number = "post----";
System.out.println("进入:"+number);
if(request!=null)
number += (String) request.get("user");
Map data = new HashMap();
data.put("number", number);
System.out.println("完成:"+number);
return CommonTool.getNodeMap(data, null);
}
//xhr,ajax对应get方法 此方法已测试成功
@RequestMapping(method = RequestMethod.GET)
//参数@RequestBody可以不写,也可以不在请求方header里设置Content-Type,而且此时Content-Type为默认application/x-www-form-urlencoded
public Map testCrossOriginGet(HttpServletRequest httpRequest) {
String number = "get----";
Map data = new HashMap();
data.put("number", number);
System.out.println("完成:"+number);
return CommonTool.getNodeMap(data, null);
}
}
结果:
一开始:报405错误,我的ajax是get请求,而后台只接收post,因此不被允许。
改成post以后,出现415错误
CORS方式解决:
服务端做出修改:(cors3中解决方案:前端-关于CORS跨域的解决方案,面向服务端)
我们新建一个CrossOriginFilter的类文件,代码如下:
package cn.edu.sdu.nydl.servlet; //我自己的包
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
public class CrossOriginFilter implements Filter{
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletResponse response = (HttpServletResponse) resp;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "0");
// response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
// response.setHeader("Content-Type", "application/json; charset=utf-8");
chain.doFilter(req, resp);
System.out.println("设置跨域请求");
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
}
这样还不行,还需要在对应项目WebContent--->WEB-INF---> web.xml 文件里面加上配置
<filter>
<filter-name>crossFilter</filter-name>
<filter-class>cn.edu.sdu.nydl.bean.web.ModifyPassword</filter-class>
</filter>
<filter-mapping>
<filter-name>crossFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
意思是项目里的所有url都可以跨域了,下面那个/*表示所有。这里我也可以写成func/testCrossOriginFeng/*
这里的接口名如何定义呢,我们看看config--->applicationContext-security.xml 文件,这里配置的是相关security信息。
参考: Spring Security(08)——intercept-url配置 https://elim.iteye.com/blog/2161056 (介绍了什么是intercept-url)
<intercept-url pattern="/func/web/**" access="permitAll" />
<intercept-url pattern="/downloads/**" access="permitAll" />
<!-- <intercept-url pattern="/func/**" access="permitAll" /> -->
<intercept-url pattern="/func/testCrossOriginFeng/**" access="permitAll" />
<!-- 3 4 行至少有一个才能保证接口可以被访问到,否则还是不能跨域 -->
现在终于open()方法可以跨域了,访问也成功返回。通过下面这个网址可以直接访问测试接口结果。restlet_client / PostMan
chrome-extension://aejoelaoggembcahagimdiliamlcdmfm/restlet_client.html#requests
前端ajax加上contentType以后就没问题了,后端:前后端必须保证前后端的contentType一致。在刚才doFilter()方法中加上response.setHeader("Content-Type", "application/json; charset=utf-8");使前后端保持一致
但是有出现了400错误,然后发现后端报错了,因为传过去的data格式不正确。
必须严格为json数据的格式。JSON格式总结下:
1)键名称:用双引号 括起
2)字符串:用使用双引号 括起
3)数字,布尔类型不需要 使用双引号 括起
正确的json格式:data:"{\"ename\":\""+$("#ename").val()+"\"}" ,静态数据格式:data:'{"user":"feng"}',
jsonp
通过在文档中嵌入一个<script>
标记来从另一个域中返回数据。只支持Get请求
在HTML标签里,一些标签比如script、img这样的获取资源的标签是没有跨域限制的,
- JSONP只支持GET请求,什么?你要提交表单,sorry,此路不通
- 它只支持跨域HTTP请求
dataType: 'jsonp',
jsonp: 'callback',
XHR2
header( "Access-Control-Allow-Origin:*" );
header( "Access-Control-Allow-Methods:POST,GET" );
XHR2
(XmlHttppRequest level2)
XMLHttpRequest 对象提供了对 HTTP 协议的完全的访问,包括做出 POST 和 HEAD 请求以及普通的 GET 请求的能力。XMLHttpRequest 可以同步或异步地返回 Web 服务器的响应,并且能够以文本或者一个 DOM 文档的形式返回内容。
在XHR诞生前,网页要获取客户端和服务器的任何状态更新,都需要刷新一次,在XHR诞生后就可以完全通过JS代码异步实现这一过程。XHR的诞生也使最初的网页制作转换为开发交互应用,拉开了WEB2.0的序幕。
XHR是一种浏览器API,极大简化了异步通信的过程,开发者并不需要关注底层的实现,因为浏览器会为我们完成这些工作,如连接管理、协议协商、HTTP请求格式化等等。最初版本的XHR能力非常有限,只支持文本传输,处理上传能力也不足,对于跨域请求也不支持。为解决这些问题,W3C于2008年发布了“XMLHttpRequest Level2”草案,新增了如下功能:
- 支持请求超时
- 支持传输二进制和文本数据
- 支持重写媒体类型和编码响应
- 支持监控每个请求的进度事件
- 支持有效的文件上传
- 支持安全的跨来源请求
2011年,W3C将“XMLHttpRequest Level2”规范与最初的“XMLHttpRequest”规范合并,所有XHR2新增的功能也都并入了原来的XHR API中,接口不变,功能增强。
不要再问我跨域的问题了
https://segmentfault.com/a/1190000015597029?utm_source=tag-newest
浅谈CSRF攻击方式
http://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html
跨域的方式
1.前端的方式: possMessage,window.name,document.domain,image.src(得不到数据返回),jsonP(script.src后台不配合得不到数据返回),style.href(得不到数据返回)
一.imge.src,script.src,style.href 不受同源策略的影响可以加载其他域的资源,可以用这个特性,向服务器发送数据。最常用的就是使用image.src 向服务器发送前端的错误信息。image.src 和style.href 是无法获取服务器的数据返回的,script.src 服务器端配合可以得到数据返回。
二possMessage,window.name,document.domain 是两个窗口直接相互传递数据。
(1)possMessage 是HTML5中新增的,使用限制是 必须获得窗口的window 引用。IE8+支持,firefox,chrome,safair,opera支持
(2)window.name ,在一个页面中打开另一个页面时,window.name 是共享的,所以可以通过window.name 来传递数据,window.name的限制大小是2M,这个所有浏览器都支持,且没有什么限制。
3) document.domain 将两个页面的document.domain 设置成相同,document.domain 只能设置成父级域名,既可以访问,使用限制:这顶级域名必须相同
2.纯后端方式: CORS,服务器代理
CORS 是w3c标准的方式,通过在web服务器端设置:响应头Access-Cntrol-Alow-Origin 来指定哪些域可以访问本域的数据,ie8&9(XDomainRequest),10+,chrom4 ,firefox3.5,safair4,opera12支持这种方式。
服务器代理,同源策略只存在浏览器端,通过服务器转发请求可以达到跨域请求的目的,劣势:增加服务器的负担,且访问速度慢。
3.前后端结合:JsonP
script.src 不受同源策略的限制,所以可以动态的创建script标签,将要请求数据的域写在src 中参数中附带回调的方法,服务器端返回回调函数的字符串,并带参数。
如 script.src="http://www.yangwei.com/?id=001&callback=getInfoCallback,服务器端返回 getInfoCallBack("name:yangwei;age:18") 这段代码会直接执行,在前面定义好getInfoCallBack函数,既可以获得数据并解析。 这种是最长见的方式。