发布:2023/12/7 15:43:29作者:大数据 来源:大数据 浏览次数:487
前端用js访问非同源资源时,就出现在前端js访问时,跨域的产生:
假设在以下index.html页面中用js使用ajax读取/访问百度https://www.baidu.com/页面内容,就出现了跨域
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<html> <head> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script> <script type="text/javascript"> $(function(){ $("#b01").click(function(){ htmlobj=$.ajax({url:"https://www.baidu.com/",async:false}); $("#myDiv").html(htmlobj.responseText); }); }); </script> </head> <body> <div id="myDiv"><h2>通过 AJAX 改变文本</h2></div> <button id="b01" type="button">改变内容</button> </body> </html> |
按F12查看浏览器错误提示
Access to XMLHttpRequest at 'https://www.baidu.com/' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
什么是同源策略?
1、同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。
2、所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。
3、同源策略限制以下几种行为:
非同源情况下
(1)Cookie、LocalStorage 和 IndexDB 无法读取
(2)DOM 和 Js对象无法获得
(3)AJAX 请求不能发送
浏览器采用同源策略,禁止页面加载或执行与自身来源不同的域的任何脚本。换句话说浏览器禁止的是来自不同源的"document"或脚本,对当前"document"读取或设置某些属性。
情景:
比如一个恶意网站的页面通过iframe嵌入了银行的登录页面(二者不同源),如果没有同源限制,恶意网页上的javascript脚本就可以在用户登录银行的时候获取用户名和密码。
浏览器中有哪些不受同源限制呢?
<script>、<img>、<iframe>、<link>这些包含 src 属性的标签可以加载跨域资源。但浏览器限制了JavaScript的权限使其不能读、写加载的内容。
常见的解决方案分为三种,Nginx代理(前端实现),JSONP(前端实现),后台设置(后端实现)。
前后端分离是目前的趋势, 解决跨域问题也是老生常谈的话题了,我们了解一下什么是域和跨域。
域:协议 + 域名 + 端口;三者完全相同则为同域,反之有其一不同均为不同域。
跨域请求:当前【发起请求】的域和【请求指向】的域属于不同域时,该次请求称之为跨域请求。
跨域问题:
同一域名下允许通信
同一域名下不同文件夹允许通信
同一域名不同端口不允许通信
同一域名不同协议不允许通信
域名和域名对应IP不允许通信
主域名相同,子域名不同不允许通信
同一域名,不同二级域名不允许通信
不同域名不允许通信
跨域请求
1、全局配置
可以通过实现WebMvcConfigurer接口然后重写addCorsMappings方法解决跨域问题。
// 请求跨域
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@Configuration public class CorsConfig implements WebMvcConfigurer { static final String ORIGINS[] = new String[] { "GET", "POST", "PUT", "DELETE" }; @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") // 所有的当前站点的请求地址,都支持跨域访问。 .allowedOrigins("*") // 所有的外部域都可跨域访问。 如果是localhost则很难配置,因为在跨域请求的时候,外部域的解析可能是localhost、127.0.0.1、主机名 .allowCredentials(true) // 是否支持跨域用户凭证 .allowedMethods(ORIGINS) // 当前站点支持的跨域请求类型是什么 .maxAge(3600); // 超时时长设置为1小时。 时间单位是秒。 } } |
2、使用 @CrossOrigin 注解
Controller层在需要跨域的类或者方法上加上该注解即可。
1 2 3 4 5 6 7 8 9 10 11 12 |
@RestController @RequestMapping("/user") @RequiredArgsConstructor @CrossOrigin(origins = "*",maxAge = 3600) public class UserController { final UserService userService; @GetMapping("/getOne/{id}") public User getOne(@PathVariable("id") Integer id) { return userService.getById(id); } } |
3、自定义跨域过滤器
1)编写过滤器
// 跨域过滤器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
@Component public class CORSFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //*号表示对所有请求都允许跨域访问 HttpServletResponse res = (HttpServletResponse) response; res.addHeader("Access-Control-Allow-Credentials", "true"); res.addHeader("Access-Control-Allow-Origin", "*"); res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT"); res.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN"); if (((HttpServletRequest) request).getMethod().equals("OPTIONS")) { response.getWriter().println("Success"); return; } chain.doFilter(request, response); } @Override public void destroy() { } @Override public void init(FilterConfig filterConfig) throws ServletException { } } |
2)注册过滤器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
@Configuration public class CorsConfig { @Bean public CorsFilter corsFilter() { CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.addAllowedOrigin("*"); corsConfiguration.addAllowedHeader("*"); corsConfiguration.addAllowedMethod("*"); corsConfiguration.setAllowCredentials(true); UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource(); urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration); return new CorsFilter(urlBasedCorsConfigurationSource); } } |
—————————————————————————
版权声明:本文为CSDN博主「旷野历程」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xhaimail/article/details/107909759
© Copyright 2014 - 2024 柏港建站平台 ejk5.com. 渝ICP备16000791号-4