Java Cors跨域处理

阅前提示:js中使用jsonp可处理跨域问题
一、CORS概述
跨源资源共享标准通过新增一系列 HTTP 头,让服务器能声明那些来源可以通过浏览器访问该服务器上的各类资源(包括CSS、图片、JavaScript 脚本以及其它类资源)。另外,对那些会对服务器数据造成破坏性影响的 HTTP 请求方法(特别是 GET 以外的 HTTP 方法,或者搭配某些MIME类型的POST请求),标准强烈要求浏览器必须先以 OPTIONS 请求方式发送一个预请求(preflight request),从而获知服务器端对跨源请求所支持 HTTP 方法。在确认服务器允许该跨源请求的情况下,以实际的 HTTP 请求方法发送那个真正的请求。服务器端也可以通知客户端,是不是需要随同请求一起发送信用信息(包括 Cookies 和 HTTP 认证相关数据)。

二、CORS原理
例如:域名A(http://a.example)的某 Web 应用程序中通过标签引入了域名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攻击的可能。

实现方式:
1、nginx配置文件配置:

server {    
    location / {    
        if ($request_method = 'OPTIONS') {    
          add_header 'Access-Control-Allow-Origin' '*';    
          add_header 'Access-Control-Allow-Credentials' 'true';    
          add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';    
          add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';    
         # add_header 'Access-Control-Max-Age' 3600;    
          add_header 'Content-Type' 'text/plain charset=UTF-8';    
          add_header 'Content-Length' 0;    
          return 200;    
        }    
}    

方法2:直接在tomcat安装目录下的lib中添加cors-filter-1.7.jar,java-property-utils-1.9.jar 这2个jar包,并且在业务项目的web.xml 中配置想要应的filter配置文件:

<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>   

方法3:自己写的 filter类,自己在在业务项目中配置web.xml 中配置想要的xml 文件。
如:java类filter:

public class CorsFilter implements Filter{  
   
@Override  
public void init(FilterConfig filterConfig) throws ServletException {  
// TODO Auto-generated method stub  
   
}  
   
@Override  
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,  
ServletException {  
// TODO Auto-generated method stub  
HttpServletResponse res = (HttpServletResponse) response;  
res.setContentType("text/html;charset=UTF-8");  
   res.setHeader("Access-Control-Allow-Origin", "*");  
   res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");  
   res.setHeader("Access-Control-Max-Age", "0");  
   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");  
   res.setHeader("Access-Control-Allow-Credentials", "true");  
   res.setHeader("XDomainRequestAllowed","1");  
   chain.doFilter(request, response);  
}  
   
@Override  
public void destroy() {  
// TODO Auto-generated method stub  
   
}  
   
}  

业务项目中的web.xml配置如下:

<filter>  
 <filter-name>cors</filter-name>  
 <filter-class>com.tianlong.common.base.CorsFilter</filter-class>  
</filter>  
<filter-mapping>  
 <filter-name>cors</filter-name>  
 <url-pattern>/*</url-pattern>  
</filter-mapping>

最新的W3C标准里是这么实现HTTP跨域请求的, Cross-Origin Resource Sharing

简单的来说,就是跨域的目标服务器要返回一系列的Headers,通过这些Headers来控制是否同意跨域。这些Headers有:4 Syntax

4.1 Access-Control-Allow-Origin HTTP Response Header
4.2 Access-Control-Max-Age HTTP Response Header
4.3 Access-Control-Allow-Credentials HTTP Response Header
4.4 Access-Control-Allow-Methods HTTP Response Header
4.5 Access-Control-Allow-Headers HTTP Response Header
4.6 Origin HTTP Request Header
4.7 Access-Control-Request-Method HTTP Request Header
4.8 Access-Control-Request-Headers HTTP Request Header

在 Request 包和 Response 包中都有一些。
其中最敏感的就是 Access-Control-Allow-Origin 这个 Header, 他是W3C标准里用来检查该跨域请求是否可以被通过。 (Access Control Check)
跨域实现的过程大致如下:
从 http://www.a.com/test.html 发起一个跨域请求,
请求的地址为: http://www.b.com/test.PHP
如果 服务器B返回一个如下的header
Access-Control-Allow-Origin: http://www.a.com
那么,这个来自 http://www.a.com/test.html 的跨域请求就会被通过。

如上所知,总结解决办法如下:

1、如果请求的url是aspx页面,则需要在aspx页面中添加代码:Response.AddHeader(“Access-Control-Allow-Origin”, “*”);

2、如果请求的url是PHP页面,则需要在PHP页面中添加代码:header(“Access-Control-Allow-Origin: *”);

3、如果请求的url是静态的html页面,则需要在页面中添加meta标签代码:

如果服务器端可以确定是要被哪些域名访问,最好是能把以上代码中的“*”代替为具体的域名,这样做可以相应的增强安全性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值