关于AJAX 跨域请求web项目/ajax跨域session问题

来源:互联网 发布:有赞 源码 编辑:程序博客网 时间:2024/06/05 14:32

近一段时间项目问题总结

关于关于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:

  1. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,  
  2. ServletException {  
  3. // TODO Auto-generated method stub  
  4. HttpServletResponse res = (HttpServletResponse) response;  
  5. res.setContentType("text/html;charset=UTF-8");  
  6.    res.setHeader("Access-Control-Allow-Origin""*");  
  7.    res.setHeader("Access-Control-Allow-Methods""POST, GET, OPTIONS, DELETE");  
  8.    res.setHeader("Access-Control-Max-Age""0");  
  9.    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");  
  10.    res.setHeader("Access-Control-Allow-Credentials""true");  
  11.    res.setHeader("XDomainRequestAllowed","1");  
  12.    chain.doFilter(request, response);  
  13. }  

  14. web.xml配置:
    1. <filter>  
    2.  <filter-name>cors</filter-name>  
    3.  <filter-class>com.aima.CorsFilter</filter-class>  
    4. </filter>  
    5. <filter-mapping>  
    6.  <filter-name>cors</filter-name>  
    7.  <url-pattern>/*</url-pattern>  
    8. </filter-mapping>  

  15. springboot中解决跨域并且session统一的配置

  16. @Configuration
    public class CorsConfig extends WebMvcConfigurerAdapter {


        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
                    .allowedOrigins("*")
                    .allowCredentials(true)
                    .allowedMethods("GET", "POST", "DELETE", "PUT")
                    .maxAge(3600);
        }
    }

  1.   以上就是跨域的一些总结,有的地方配置的也不够仔细,如有问题,请各位指教!
  2.