好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

前后端分离后,JavaWeb开发如何解决跨域问题

做Web开发,经常会遇到跨域问题,小伙伴们在面试中,也经常被问到。这不,又有一位工作3年的小伙伴被问到这样一道题,说前后端分离后,如果解决跨域问题。

今天,我给大家分享一下我的理解。

这个问题也有很多小伙伴单独问过我,很多小伙伴知道如何解决跨域问题,但是却说不清楚跨域到底是怎么产生的。所以,回答跨域解决方案之前,我们先来介绍一下跨域产生的原因。

1、产生原因

因为一般的浏览器都有一个安全机制,叫做同源策略限制。所谓同源策略就是指用户输入的URL中包含的协议、域名、端口都完全相同。也就是说,我们使用浏览器访问网页时,必须符合同源策略的请求才能访问。如果有一项不同,浏览器会觉得有安全风险,就不想让你使用这个接口的数据。

 

比如,在http://localhost:8080/index 页面中,用Ajax访问https://localhost:8081/index.json接口数据的时候,这两个URL的协议和端口不相同,也就是不同源,这就产生了跨域访问。当然,浏览器还是会将这个请求发送到后台服务器,但是,浏览器不会接收服务器响应结果。

举个更通俗的例子,就好比你去肯德基点餐,非要点一碗兰州拉面,店员虽然很鄙视你,但他还是会打电话问一下兰州拉面馆问一下,兰州拉面馆说不给肯德基供货。所以,你没有吃到兰州拉面。这其中,有个反常的操作,就是虽然你点的兰州拉面,但是肯德基店员还是帮你打电话问了,是拉面馆不给肯德基供货的,如果拉面馆说给肯德基供货而且把面送过来了,那么你就能吃到兰州拉面了。

这个案例中,店员就相当于是浏览器,肯德基呢就相当于当前看到的网页,兰州拉面馆就是相当于后台服务的接口。肯德基和兰州拉面不是同一个老板,相当于是不同源。拉州拉面就是你想要的接口数据。

但如果使用Postman等开发工具进行交互是不会出现跨域问题的,这是浏览器特有的限制。

其实,跨域问题也并不是前后端分离后才有的,后端开发的程序员一般都遇到过跨域问题。只是前后端分离开发以后,前端开发体现跨域问题更加明显了,经常要找后端开发人员来解决。

2、预检请求

为了支持跨域访问,浏览器设置了预检机制。也就是说在发出跨域请求时, 浏览器会自动发出一个查询请求,称为预检请求, 用来确认目标资源是否支持跨域。

 

如果请求要满足以下条件,浏览器才不会发送预检请求:

 

(1)请求方法是GET 、PosT .HEAD其中任意一个

(2)请求头中包含Accept、Accept-Language、Content-Language、Content-Type、DPR、Downlink、Save-Data、Viewport.Width、Width字段。

(3)Content-Type的值是text/plain 、multipart/form-data ,application/x-ww-form-urlencoded 中任意一个。

 

但是,在实际项目开发中,我们请求的Content-Type一般是是text/html、application/json等格式,或者使用自定义请求头,都会触发预检请求。

浏览器获取到预检请求的响应结果之后,判断服务器如果授权允许访问这个资源,就会再次请求真正的URL,如果不允许就会报这样一个错。

has been blocked by CORS policy : No 'Access-contro1-A11ow-Origin' header is present on the requested resource.

3、如何解决

我们可以利用浏览器的预检机制。

我只需要在后端服务添加CORS策略的配置就可以解决跨域问题。CORS全称是Cross Origin Resource Sharing,翻译过来叫做跨域资源共享。具体解决方案,有以下4种:

1)如果是普通的Web项目,只需要在服务的根目录下添加一个crossdomain.xml文件即可。文件格式如下:

 < ?xml version =  "1.0" ? >    DOCTYPE cross - domain - policy SYSTEM  "http://HdhCmsTestadobe测试数据/xml/dtds/cross-domain-policy.dtd"  >   < cross - domain - policy >   < site - control permitted - cross - domain - policies =  "all"  />   < allow - access -  from  domain =  "*"  />   < allow - access -  from  domain =  "*"  />   < allow - http - request - headers -  from  domain =  "*"  headers =  "*"  />    cross - domain - policy >   

当然,使用这种方式不够灵活,在授权过度的情况下,会存在一些安全隐患。

2)如果是Spring项目的话,可以添加一个处理跨域的过滤器或者拦截器。如代码所示:

public class CorsFilter implements Filter  {  @Override 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"  )  ;  chain .doFilter  ( req ,  res )  ;   }   } 

3)如果是Spring Boot项目的话,只需要在方法上添加@CrossOrigin注解即可,如代码所示:

@GetMapping (  "/list"  )  @CrossOrigin public List < String >  list (  )  {  ...  } 

如果需要支持跨域的方法非常多情况下,可以添加过滤器,比Spring更简洁,如代码所示:

 

@Configuration public class CorsConfig  {  @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 )  ;   }   } 

4)Spring Boot项目还有一种更方便的方式,可以实现WebMvcConfigurer接口来实现跨域支持,如代码所示:

 

@Configuration public class CorsConfiguration implements WebMvcConfigurer  {  @Override public void addCorsMappings ( CorsRegistry registry )   {  registry .addMapping  (  "/**"  )   .allowed0riginPatterns  (   "*"  )   .allowedMethods  (  "GET"  ,  "POST"  ,  "PUT" , "DELETE" , "HEAD"  ,  "OPTIONS"  )   .allowCredentials  (  true  ) I  .maxAge  (  3600  )   .allowedHeaders  (  "*"  )  ; l  }   } 

只需要重写addCorsMapping() 方法就可以了。

以上就是对Java Web跨域问题的解决方案。

原文地址:https://mp.weixin.qq测试数据/s/6hkcMpDPVjmvdLqaN686tg

查看更多关于前后端分离后,JavaWeb开发如何解决跨域问题的详细内容...

  阅读:26次