飞道的博客

SpringBoot处理跨域总结

473人阅读  评论(0)

解决跨域的五种方法

1、CorsFilter

新建一个类


   
  1. @Configuration
  2. public class CorsConfig {
  3. @Bean
  4. public CorsFilter corsFilter () {
  5. //1. 添加 CORS配置信息
  6. CorsConfiguration config = new CorsConfiguration();
  7. //放行哪些原始域
  8.         //springboot版本为2.4.0以前写法
  9. config.addAllowedOrigin( "*");
  10.         //springboot版本为2.4.0以后写法
  11.         config.setAllowedOriginPatterns(Collections.singletonList( "*"));
  12.         //查看项目的springboot版本
  13.         //System.out.println(SpringBootVersion.getVersion());
  14. //是否发送 Cookie
  15. config.setAllowCredentials( true);
  16. //放行哪些请求方式
  17. config.addAllowedMethod( "*");
  18. //放行哪些原始请求头部信息
  19. config.addAllowedHeader( "*");
  20. //暴露哪些头部信息
  21. config.addExposedHeader( "*");
  22. //2. 添加映射路径
  23. UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
  24. corsConfigurationSource.registerCorsConfiguration( "/**",config);
  25. //3. 返回新的CorsFilter
  26. return new CorsFilter(corsConfigurationSource);
  27. }
  28. }

2、重写 WebMvcConfigurer


   
  1. @Configuration
  2. public class CorsConfig implements WebMvcConfigurer {
  3. @Override
  4. public void addCorsMappings (CorsRegistry registry) {
  5. registry.addMapping( "/**")
  6. //是否发送Cookie
  7. .allowCredentials( true)
  8. //放行哪些原始域
  9. .allowedOrigins( "*")
  10. .allowedMethods( new String[]{ "GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"})
  11. .allowedHeaders( "*")
  12. .exposedHeaders( "*");
  13. }
  14. }

3、使用注解


   
  1. @RestController
  2. @CrossOrigin(origins = "*")
  3. public class CorsController {
  4. @RequestMapping("/cors")
  5.     @CrossOrigin(origins = "*")
  6. public String cors () {
  7. return "cors";
  8. }
  9. }

4、手动设置响应头


   
  1. @RequestMapping("/cors")
  2. public String cors (HttpServletResponse response) {
  3. response.addHeader( "Access-Allow-Control-Origin", "*");
  4. return "cors";
  5. }

5、使用自定义filter


   
  1. import org.springframework.context.annotation.Configuration;
  2. import javax.servlet.*;
  3. import javax.servlet.annotation.WebFilter;
  4. import javax.servlet.http.HttpServletResponse;
  5. import java.io.IOException;
  6. @WebFilter(filterName = "CorsFilter ")
  7. @Configuration
  8. public class CorsFilter implements Filter {
  9. @Override
  10. public void doFilter (ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
  11. HttpServletResponse response = (HttpServletResponse) res;
  12. response.setHeader( "Access-Control-Allow-Origin", "*");
  13. response.setHeader( "Access-Control-Allow-Credentials", "true");
  14. response.setHeader( "Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT, OPTIONS");
  15. response.setHeader( "Access-Control-Max-Age", "3600");
  16. response.setHeader( "Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  17. chain.doFilter(req, res);
  18. }
  19. }

模拟跨域

跨域的拦截是浏览器行为,所以后端开发的时候不会遇到这个问题,只有在联调的时候才会发现,这种问题前端、后端都可以解决。前端通过代理请求同一域的一个接口,然后转发到后端。后端则通过在Response Header设置值解决。而后端本地测试跨域配置是否生效时比较麻烦,因为是浏览器问题,发布到测试环境流程长,所以需要本地也能复现跨域问题,其实也比较简单,只不过需要百度一些前端代码[狗头]

首先,先随便找一个网站,然后在Console向本地发送Http请求就能模拟跨域了。


   
  1. // 普通请求
  2. var xhr = new XMLHttpRequest();
  3. xhr.open( 'OPTIONS', 'http://127.0.0.1:8080/test1');
  4. xhr.send();
  5. xhr.onload = function(e) {
  6. var xhr = e.target;
  7. console.log(xhr.responseText);
  8. }
  9. // GET请求
  10. var xhr = new XMLHttpRequest();
  11. xhr.open( 'GET', 'http://127.0.0.1:8080/test1?a=1');
  12. xhr.send();
  13. xhr.onload = function(e) {
  14. var xhr = e.target;
  15. console.log(xhr.responseText);
  16. }
  17. // 携带header
  18. var xhr = new XMLHttpRequest();
  19. xhr.open( 'GET', 'http://127.0.0.1:8080/test1?a=1');
  20. xhr.setRequestHeader( 'content-type', 'application/json');
  21. xhr.setRequestHeader( 'signature', 'gaejhgkaehguiaehiuavoihvoihviehviehiohao');
  22. xhr.send();
  23. xhr.onload = function(e) {
  24. var xhr = e.target;
  25. console.log(xhr.responseText);
  26. }
  27. // POST请求
  28. var xhr = new XMLHttpRequest();
  29. xhr.open( 'POST', 'http://127.0.0.1:8080/test1?a=1');
  30. xhr.setRequestHeader( 'content-type', 'application/json');
  31. xhr.setRequestHeader( 'signature', 'gaejhgkaehguiaehiuavoihvoihviehviehiohao');
  32. xhr.send( "{a:1,b:2}");
  33. xhr.onload = function(e) {
  34. var xhr = e.target;
  35. console.log(xhr.responseText);
  36. }

跨域问题踩过的坑

这些问题主要是网上代码都是抄来抄去,有一些人抄的时候删了一些或者copy漏了,导致代码不全,然后又因为浏览器的一些机制导致了还是存在跨域问题,坑了后面的人。

踩坑一:没有允许OPTIONS请求跨域

比如用上面的方案二来处理跨域问题

乍一看没有什么问题,只是不支持OPTIONS请求,但是浏览器在处理跨域请求的时候,会先发送一个OPTIONS请求去检测服务是否允许跨域请求,然后再去请求服务要数据之类的。所以这里根本没解决,联调时还是会有跨域问题。

踩坑二:没有允许Credentials

场景:后端不允许前端传递用户凭证,但是前端请求的时候带上了,这时浏览器也会报跨域错误

用户凭证是用户登录之后,服务器下发的一些凭证,如cookie。在跨域请求中,浏览器并不会把cookie携带上,但是可以通过js代码携带上。

使用上面方案一,不允许用户凭证


转载:https://blog.csdn.net/qq_41084438/article/details/128703767
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场