允许跨域的方式
1、JSONP,只能发出get请求
使用<script src="">来完成一个跨域请求:
当点击"跨域获取数据"的按钮时,添加一个<script>标签,用于发起跨域请求;注意看请求地址后面带了一个callback=showData的参数;
showData即是回调函数名称,传到后台,用于包裹数据。数据返回到前端后,就是showData(result)的形式,因为是script脚本,所以自动调用showData函数,而result就是showData的参数。
至此,我们算是跨域把数据请求回来了,但是比较麻烦,需要自己写脚本发起请求,然后写个回调函数处理数据,不是很方便。
1 //回调函数 2 function showData (result) { 3 var data = JSON.stringify(result); //json对象转成字符串 4 $("#text").val(data); 5 } 6 7 $(document).ready(function () { 8 9 $("#btn").click(function () { 10 //向头部输入一个脚本,该脚本发起一个跨域请求 11 $("head").append("<script src='http://localhost:9090/student?callback=showData'></script>"); 12 }); 13 14 });
服务端:
1 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 2 response.setCharacterEncoding("UTF-8"); 3 response.setContentType("text/html;charset=UTF-8"); 4 5 //数据 6 List<Student> studentList = getStudentList(); 7 8 9 JSONArray jsonArray = JSONArray.fromObject(studentList); 10 String result = jsonArray.toString(); 11 12 //前端传过来的回调函数名称 13 String callback = request.getParameter("callback"); 14 //用回调函数名称包裹返回数据,这样,返回数据就作为回调函数的参数传回去了 15 result = callback + "(" + result + ")"; 16 17 response.getWriter().write(result); 18 }
jquery的jsonp方式跨域请求:
服务端代码不变,js代码如下:最简单的方式,只需配置一个dataType:'jsonp',就可以发起一个跨域请求。jsonp指定服务器返回的数据类型为jsonp格式,可以看发起的请求路径,自动带了一个callback=xxx,xxx是jquery随机生成的一个回调函数名称。
这里的success就跟上面的showData一样,如果有success函数则默认success()作为回调函数。
1 $(document).ready(function () { 2 3 $("#btn").click(function () { 4 5 $.ajax({ 6 url: "http://localhost:9090/student", 7 type: "GET", 8 dataType: "jsonp", //指定服务器返回的数据类型 9 success: function (data) { 10 var result = JSON.stringify(data); //json对象转成字符串 11 $("#text").val(result); 12 } 13 }); 14 15 }); 16 17 });
指定回调函数至于在上面加上 jsonpCallback: "showData", //指定回调函数名称,但success()方法在调用过指定回调函数后仍会调用。
2、CORS
1、在允许跨域访问的方法内设置response,只允许此方法跨域访问
1 response.addHeader("Access-Control-Allow-Origin", "*"); 2 response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE"); 3 response.addHeader("Access-Control-Allow-Headers", "Content-Type"); 4 response.addHeader("Access-Control-Max-Age", "1800");//30 min
2、在拦截器中配置,配置在项目的web.xml中时,整个项目接口均允许跨域
<filter> <filter-name>cros</filter-name> <filter-class>cn.ifengkou.test.filter.CORSFilter</filter-class> </filter> <filter-mapping> <filter-name>cros</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
@Component public class CORSFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { response.addHeader("Access-Control-Allow-Origin", "*"); response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE"); response.addHeader("Access-Control-Allow-Headers", "Content-Type"); response.addHeader("Access-Control-Max-Age", "1800");//30 min filterChain.doFilter(request, response); } }
3、SpringMVC提供@CrossOrigin注解允许跨域,加载类上表示整个controller都可跨域,用在方法上表示此方法允许跨域
4、tomcat配置允许跨域
5、nginx配置允许跨域
#
# Wide-open CORS config for nginx
#
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
}
注意:重定向的跨域访问中 Access-Control-Allow-Origin的值不能设置为‘*’,必须设置为具体的源
shiro中对跨域的支持
对简单请求支持,非简单请求时需重写 FormAuthenticationFilter中的isAccessAllowed方法
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { return request instanceof HttpServletRequest && ((HttpServletRequest)request).getMethod().toUpperCase().equals("OPTIONS") ? true : super.isAccessAllowed(request, response, mappedValue); }
跨域请求时,浏览器会过滤相关响应头中自定义的key,想要不过滤,在服务端响应头中写入不需过滤的key
response.setHeader("Access-Control-Expose-Headers", "所要展示的key")