JavaWeb(跨域和前后分离)

 跨域问题

什么是跨域

简单的说即为浏览器限制访问A站点下的js代码对B站点下的url进行ajax请求。比如说,前端域名是www.abc.com,那么在当前环境中运行的js代码,出于安全考虑,访问www.xyz.com域名下的资源,是受到限制的。现代浏览器默认都会基于安全原因而阻止跨域的ajax请求,这是现代浏览器中必备的功能,但是往往给开发带来不便。特别是对我这样后台开发人员来讲,这个事情简直神奇。
但跨域的需求却一直都在,为了跨域,勤劳勇敢的程序猿们想出了许许多多的方法,例如,jsonP、代理文件等等。但这些做法增加了许多不必要的维护成本,而且应用场景也有许多限制,例如jsonP并非XHR,所以jsonP只能使用GET传递参数。更详细的资料可以看这里 Web应用跨域访问解决方案汇总


1. 跨域的产生:当前页面的URL与要发送的XHR请求的服务器端URL有以下任何一个不同都会产生跨域的问题:协议(如:http和https)、主机(即使是127.0.0.1和localhost也是不同主机)、端口

2. 解决方式1:JSONP

A. 客户端:

1) 使用jquery的ajax库函数:在发送请求时,指定dataType为jsonp,则请求时会自动添加表示回调函数的参数(默认参数名是callback,可以通过ajax方法的jsonp配置项修改)

2) 原生方式:在请求的url地址后添加参数,指明回调函数名

B. 服务器端:获取表示回调函数的参数值,如果有,则将参数值与数据拼接成函数调用的格式输出;如果没有则直接输出数据

3. 解决方式2:CORS

CORS协议

如今的JS大有一统天下的趋势,浏览器已经成了大多应用最好的安身之所。哪怕在移动端也有各种Hybird方案,在本地文件系统的Web页面,也有需要获取外部数据的需求,而这些需求也必然是跨域的。在寻找跨域解决方案时,发现了最优雅解决方案就是HTML5来带了的“Cross-Origin Resource Sharing”的新特性,来赋予开发者权力决定资源是否允许被跨域访问。
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
为什么说它优雅呢?
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
解决这个问题的关键就落在了我这个负责后台的程序猿身上。
看看文档也不是什么难事嘛,就是需要在http头中设置Access-Control-Allow-Origin来决定需要允许哪些站点来访问。关于CROS协议更详细内容参考跨域资源共享 CORS 详解

CROS常见header

CORS具有以下常见的header

Access-Control-Allow-Origin: http://kbiao.me  

Access-Control-Max-Age: 3628800

Access-Control-Allow-Methods: GETPUT, DELETE

Access-Control-Allow-Headers: content-type

"Access-Control-Allow-Origin"表明它允许" http://kbiao.me "发起跨域请求

"Access-Control-Max-Age"表明在3628800秒内,不需要再发送预检验请求,可以缓存该结果(上面的资料上我们知道CROS协议中,一个AJAX请求被分成了第一步的OPTION预检测请求和正式请求)

"Access-Control-Allow-Methods"表明它允许GET、PUT、DELETE的外域请求

"Access-Control-Allow-Headers"表明它允许跨域请求包含content-type头

当然在处理这个问题的时候前端也有不少坑,特别是Chrome浏览器不允许localhost的跨域请求,

A. 优点:支持POST方式、安全性高(可以限制访问来源)、几乎无需修改代码

B. 实现:Tomcat8+版本直接配置CorsFilter过滤器或者在springboot下的和application启动类在同一个目录下即可

3-1 springmvc框架下解决方法:

@Component 是Spring的注解,关键部分在doFilter中,添加了我们需要的头,option是预检测需要所以需要允许,Authorization是做了oauth2登录响应所必须的,Access-Control-Allow-Credentials表示允许cookies。都是根据自己项目的实际需要配置。

再配置Web.xml使得过滤器生效

/**

 * Created on 2018/7/5.

 */
@Component
public class myCORSFilter implements Filter {

 

    @Override

    public void init(FilterConfig filterConfig) throws ServletException {

 

    }

 

    @Override

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        HttpServletResponse response = (HttpServletResponse) servletResponse;

        String origin = (String) servletRequest.getRemoteHost()+":"+servletRequest.getRemotePort();

        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,Authorization");

        response.setHeader("Access-Control-Allow-Credentials","true");

        filterChain.doFilter(servletRequest, servletResponse);

    }

 

    @Override

    public void destroy() {

 

    }}



  cors

  ·CLASS_PATH·.myeCORSFilter

  cors

  /api/*

接下来前端就可以像往常一样使用AJAX请求获得资源了,完全不需要做出什么改变。

SPRING 4中更优雅的办法

SpringMVC4提供了非常方便的实现跨域的方法。在requestMapping中使用注解。
@CrossOrigin(origins = “http://kbiao.me”)
全局实现 .定义类继承WebMvcConfigurerAdapter,设置跨域相关的配置

public class CorsConfigurerAdapter extends WebMvcConfigurerAdapter{

 

  @Override

  public void addCorsMappings(CorsRegistry registry) {

 

    registry.addMapping("/api/*").allowedOrigins("*");

  }}

将该类注入到容器中:

 class="com.tmall.wireless.angel.web.config.CorsConfigurerAdapter">


3-2  微服务框架下的解决:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

/** 
 *  
* @author liuyinfei
* @version 1.0
* @taskId
* @CreateDate 2018年07月05日
*/ @Configuration public class GatewayConfiguration { /** * Description: 设置跨域测试
* @taskId
* @return
*/ @Bean public CorsFilter corsFilter() { CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.addAllowedOrigin("*"); corsConfiguration.addAllowedHeader("*"); corsConfiguration.addAllowedMethod("*"); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", corsConfiguration); return new CorsFilter(source); } }

你可能感兴趣的:(cors)