Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 593|回复: 0

ajax跨域请求接口介绍及解决方案

[复制链接]
  • TA的每日心情
    奋斗
    4 天前
  • 签到天数: 802 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726006
    发表于 2021-7-22 07:35:09 | 显示全部楼层 |阅读模式
    在前端开发过程中,将常出现前端代码和后台服务不在一个服务器的情况,这时候前端js代码调用后台接口,会出现跨域问题。:
    1、这里的域是通过URL的头部来识别的。浏览器并不会去尝试判断相同的ip地址对应着两个域或者两个域是否在同一个ip上。URL的头部指window.location.protocol +window.location.host,也可以理解为“Domains, protocols and ports must match”。
    2、因为协议、IP、端口造成的跨域问题,只修改前端代码是没用的。
    下面我们主要讲述前端和后台服务器不在同一域名下,引起的跨域问题。如果前端js跨域访问后台接口,浏览器控制台会报错。
     
    可用通过两种方式解决:JSONP和CORS。
    一、JSONP
    JSONP可以实现GET请求的跨域访问。
    前端代码:
     
    简写形式,效果相同
     
     
    后台Java代码:
     
    PrintWriter out = response.getWriter(); JSONObject resultJSON = JSONObject.fromObject(map); //根据需要拼装json String jsonpCallback = request.getParameter("jsonpCallback");//客户端请求参数 out.println(jsonpCallback+"("+resultJSON.toString(1,1)+")");//返回jsonp格式数据
     
     
    二、CORS
    CORS定义一种跨域访问的机制,可以让AJAX实现跨域访问。CORS 允许一个域上的网络应用向另一个域提交跨域 AJAX 请求。
    CORS与JSONP相比,无疑更为先进、方便和可靠。
    1、 JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求。
    2、 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理。
    3、 JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS。
    使用CORS,需要区分简单请求和预检机制。
    在CORS规范中,GET、HEAD和POST这三个HTTP是“简单HTTP方法”,Accept, Accept-Language, Content-Language和报头Content-Type为multipart/form-data、application/x-www-form-urlencoded、text/plain中一种的称为“简单请求报头”。
    简单请求:请求采用简单HTTP方法,自定义请求报头空或者自定义请求报头均为简单请求报头。因为具有这些特性的请求不是以更新(添加、修改和删除)资源为目的,服务端对请求的处理不会导致自身维护资源的改变。如果是简单请求,设置Access-Control-Allow-Origin为请求站点IP或者*即可。
    预检机制:浏览器在发送真正的跨域资源请求前,先发送一个预检请求(Preflight Request)。预检请求为一个采用HTTP-OPTIONS方法的请求,这是一个不包含主体的请求,同时用户凭证相关的报头也会被剔除。基于真正资源请求的一些辅助授权的信息会包含在此预检请求的相应报头中。
    资源的提供者在接收到预检请求之后,根据其提供的相关报头进行授权检验,确定请求站点是否值得信任,请求采用HTTP方法和自定义报头是否被允许。如果预检请求没有通过授权检验,资源提供者一般会返回一个状态为“400, Bad Reuqest”的响应。如果通过,则会返回一个状态为“200, OK”的响应,授权相关信息会包含在响应报头中。除了上面介绍的“Access-Control-Allow-Origin”报头之外,预检请求的响应还具有如下3个典型的报头。
    Access-Control-Allow-Methods:跨域资源请求允许采用的HTTP方法列表。
    Access-Control-Allow-Headers:跨域资源请求允许携带的自定义报头列表。
    Access-Control-Max-Age:浏览器可以将响应结果进行缓存的时间(单位为秒),这样可以让浏览器避免频繁地发送预检请求。
    浏览器在接收到预检响应之后,会根据响应报头确定后续发送的真正跨域资源请求是否会被接受,具体的检验逻辑如下:
    通过请求的“Origin”报头表示的源站点必须存在于“Access-Control-Allow-Origin”响应报头标识的站点列表中。
    l 响应报头“Access-Control-Allow-Methods”不存在,或者预检请求的“Access-Control-Request-Method”报头表示的请求方法在其列表之内。
    l 预检请求的“Access-Control-Request-Headers”报头存储的报头名称均在响应报头“Access-Control-Allow-Headers”表示的报头列表之内。
    只有在确定服务端一定会接受的情况下,浏览器才会发送真正跨域资源请求。预检响应结果会被浏览器缓存,在“Access-Control-Max-Age”报头设定的时间内,缓存的结果将被浏览器用户进行授权检验,所以在此期间不会再有预检请求发送。
    在W3C的CORS规范来说,服务端利用响应报头“Access-Control-Allow-Credentials”来表明自身是否支持用户凭证。这里的用户凭证类型包括Cookie、HTTP-Authentication报头以及客户端X.509证书(采用支持客户端证书的TLS/SSL)等。如果设置“Access-Control-Allow-Credentials”为true,那么“Access-Control-Allow-Origin”不能为”*”,必须是指定的站点。
    有预检机制的后台代码设置:
    response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers","x-requested-with,content-type");
     
     
    可以建立一个Filter
    package com.chinamobile.cmss.bcse.web.interceptor; 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; import org.springframework.stereotype.Component; @Component public class SimpleCORSFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) res; response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); response.setHeader("Access-Control-Max-Age","3600"); response.setHeader("Access-Control-Allow-Headers","x-requested-with, content-type"); chain.doFilter(req, res); } public void init(FilterConfig filterConfig) {} public void destroy() {} }
     
     
    在web.xml中添加代码:
    <filter> <filter-name>cors</filter-name> <filter-class>com.chinamobile.cmss.bcse.web.interceptor.SimpleCORSFilter</filter-class> </filter> <filter-mapping> <filter-name>cors</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
     
     
    也可以只修改web.xml。在maven框架中添加maven依赖
    <dependency> <groupId>com.thetransactioncompany</groupId> <artifactId>cors-filter</artifactId> <version>2.5</version> </dependency>
     
     
    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,OPTION</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> <init-param> <param-name>cors.maxAge</param-name> <param-value>3600</param-value> </init-param></filter> <filter-mapping> <filter-name>CORS</filter-name> <url-pattern>/*</url-pattern></filter-mapping>
    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-11-15 12:33 , Processed in 0.374714 second(s), 27 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表