Cors解决跨域问题

当一个资源从与该资源本身所在的服务器不同的域或端口请求一个资源时,资源会发起一个跨域 HTTP 请求(下图来源网络)。出于安全性考虑,浏览器会限制或拦截跨域的请求,这样的场景非常多,同时也衍生了许多解决跨域的方法。例如我在http://localhost:8080上面的ajax请求http://localhost:9090上面的服务,报错如下

jquery.min.js:4 Failed to load http://localhost:9090/testJsonp?format=json: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.
本篇利用cors(跨域资源共享)技术来解决ajax跨域问题。cors是通过目标服务器返回的Header设置来控制是否可跨域。其中重要的一个参数即 Access-Control-Allow-Origin(访问控制允许来源),通过这个参数指定可以接收的请求资源。从实现上来说,用拦截器或过滤器均可。


使用示例

<!-- web.xml中添加如下 -->
<filter>
   <filter-name>corsFilter</filter-name>
   <filter-class>com.simonsfan.cn.filter.CorsFilter</filter-class>
   <init-param>
      <param-name>allowOrigin</param-name>
      <param-value>http://×××.com</param-value>;
   </init-param>
   <init-param>
      <param-name>allowMethods</param-name>
      <param-value>GET,POST,PUT,DELETE,OPTIONS</param-value>
   </init-param>
   <init-param>
      <param-name>allowCredentials</param-name>
      <param-value>true</param-value>
   </init-param>
   <init-param>
      <param-name>allowHeaders</param-name>
      <param-value>Content-Type</param-value>
   </init-param>
</filter>
<filter-mapping>
   <filter-name>corsFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>     
如上在web.xml中定义了cors用到的一些常量,这些常量也可以直接定义为枚举或普通常量下面的CorsFilter类中

allowOrigin:允许来源(协议+域名+端口);

allowMethods:Http请求方法(get/post/put/delete/options);

allowCredentials:是否允许发送cookie及Http认证信息到服务端(true/false);

allowHeaders:目标服务器支持的头信息字段(Content-Type);
自定义过滤器CorsFilter类
public class CorsFilter implements Filter {
    private String allowOrigin;
    private String allowMethods;
    private String allowCredentials;
    private String allowHeaders;
    private String exposeHeaders;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        allowOrigin = filterConfig.getInitParameter("allowOrigin");
        allowMethods = filterConfig.getInitParameter("allowMethods");
        allowCredentials = filterConfig.getInitParameter("allowCredentials");
        allowHeaders = filterConfig.getInitParameter("allowHeaders");
        exposeHeaders = filterConfig.getInitParameter("exposeHeaders");
    }

    @Override
    public void destroy() {
    }

   @Override
   public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
         ServletException {
      HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        if (!StringUtils.isEmpty(allowOrigin)) {
            List<String> allowOriginList = Arrays.asList(allowOrigin.split(","));
            if (!CollectionUtils.isEmpty(allowOriginList)) {
                String currentOrigin = request.getHeader("Origin");
                if (allowOriginList.contains(currentOrigin)) {
                    response.setHeader("Access-Control-Allow-Origin", currentOrigin);
                }
            }
        }
        if (!StringUtils.isEmpty(allowMethods)) {
            response.setHeader("Access-Control-Allow-Methods", allowMethods);
        }
        if (!StringUtils.isEmpty(allowCredentials)) {
            response.setHeader("Access-Control-Allow-Credentials", allowCredentials);//是否允许发送cookie和http认证信息到服务器
        }
        if (!StringUtils.isEmpty(allowHeaders)) {
            response.setHeader("Access-Control-Allow-Headers", allowHeaders);
        }
        if (!StringUtils.isEmpty(exposeHeaders)) {
            response.setHeader("Access-Control-Expose-Headers", exposeHeaders);
        }
        chain.doFilter(request, response);
   }
}
注意:如上代码是写在被调用方的服务中。

Cors对比jsonp

Cors可以实现和jsonp同样的效果,但是比jsonp强大些,它支持所有类型的http请求,而jsonp只支持get方式的请求。上述代码顺利解决ajax跨域问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值