十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

《SpringBoot 3:入门与应用实战》第 9 章 跨域问题 阅读笔记 27

《SpringBoot 3:入门与应用实战》第 9 章 跨域问题 阅读笔记 27 《SpringBoot 3入门与应用实战》第 9 章 跨域问题 阅读笔记 2710.4 跨域问题10.4.1 同源策略与跨域问题跨域是一种现象跨域是由浏览器的同源策略引起的而同源策略是在浏览器上对资源的一种安全保护策略同源策略最初只是用于保护网页的Cookie后来对同源的要求越来越严格。同源策略规定了 3 个“相同”条件协议相同、域名相同、端口相同当这 3 个条件都满足时浏览器才会认为访问的资源是同一个来源。同源策略的保护目标主要是 Cookie。试想如果访问一个银行的网站当登录银行电子账户的同时又在浏览器中访问了别的网站如果此时浏览器没有同源策略的保护那么浏览器中存放的银行网站的 Cookie 会一并发送给别的网站。万一这个网站中有隐藏的攻击脚本那么银行账户就会陷入危机。因此同源策略主要保护的是上网安全。简单地说跨域就好比你在访问 https://a.com/ 域名下的网页这个网页中 Ajax 请求 https://a.cn/ 的资源​此时就会构成跨域访问。因为当前的网页所在域名是 a.com但网页内部访问的资源有不是当前域名的内容所以就构成了跨域访问。只要触发以下 3 种情况之一就会引起跨域问题。HTTP访问HTTPS或者HTTPS访问HTTP。不同域名之间的访问。不同端口之间的访问。目前浏览器的同源策略在处理跨域问题时的态度有如下 3 种。非同源的 Cookie、localstorage、indexedDB 无法访问。非同源的 iframe 无法访问防止加载其他网站的页面元素​。非同源的 Ajax 请求可以访问但浏览器拒绝接收响应。10.4.2 演示跨域现象要搭建能触发跨域问题的工程环境可以借助 IDEA 构建两个工程运行实例通过修改不同的 Web 容器端口就可以启动两个工程模拟基于端口的跨域相对容易操作​。1.IDEA 设置启动配置依次单击 IDEA 的菜单栏的 “Run→Edit Configuration…”​在弹出的对话框中选中当前的 SpringBootWebMvcApplication 主启动类后单击左上角的“复制”按钮并在 “Build and run” 栏中添加运行参数 -Dserver.port8081之后单击 “保存” 就生成了一个在 8081 端口运行的 WebMvc 工程副本。2.准备测试代码接下来需要在页面中构造一个跨域的 Ajax 请求在 userList.html 页面文件中找到 “批量删除” 按钮对应的事件绑定代码将发送 Ajax 请求的地址改为发送到 8081 端口的实例上。!DOCTYPEhtmlhtmllangzhxmlns:thhttp://www.thymeleaf.orgheadmetacharsetUTF-8title用户列表/titlescriptsrchttps://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.js/script/headscriptfunctiondel(id){if(confirm(是否删除用户)){window.locationdocument.getElementById(delete-link).getAttribute(href)?idid;}}$(function(){$(#batch-delete-button).click(function(){varselectedIds$([nameselectedId]:checked);varids[];for(vari0;iselectedIds.length;i){ids.push(selectedIds[i].value);}// $.post([[{/user/batchDelete}]], {ids: ids}, function(data) {// alert(data)// });$.post(http://localhost:8081/springboot-webmvc-a/user/batchDelete2,{ids:ids},function(data){alert(data)});});$(#batch-update-button).click(function(){$(#batch-update-form).submit();});});/scriptbodyh3用户列表/h3divformidquery-formmethodgetth:action{/user/list}label用户名/labelinputtypetextnameusernamevalueinputtypesubmitvalue查询/formbuttonidbatch-delete-button批量删除/buttonbuttonidbatch-update-button批量修改用户名/button/divtableiduser-tableborder1theadtrthwidth40px/ththwidth320pxid/ththwidth150px用户名/ththwidth100px姓名/ththwidth150px生日/ththwidth150px头像/ththwidth150px所属部门/ththwidth100px操作/th/tr/theadtbodyformidbatch-update-formth:action{/user/batchUpdate}methodposttrth:eachuser,userstatus : ${userList}tdaligncenterinputtypecheckboxnameselectedIdth:value${user.id}/tdtdaligncenter[[${user.id}]]/tdtdaligncenterinputtypetextth:name|users[${userstatus.index}].username|th:value${user.username}/tdtdaligncenter[[${user.name}]]/tdtdaligncenter[[${#dates.format(user.birthday, yyyy-MM-dd)}]]/tdtdaligncenterimgth:src{|/user/getPhoto?id${user.id}|}//tdtdaligncenter[[${user.department.name}]]/tdtdaligncenterath:href{|/user/edit?id${user.id}|}编辑/aath:href|javascript:del(${user.id})|删除/a/td/tr/form/tbody/tableaiddelete-linkth:href{/user/delete}styledisplay:none/a/body/html对应地要编写一个接口接收该请求。注意这次发送的请求 URI 前缀为 /springboot-webmvc-a/user/batchDelete2需要再编写一个新的方法。3.测试效果代码准备完毕接下来分别启动两个应用在浏览器中访问 http://localhost:8080/springboot-webmvc-a/user/list勾选几个用户后单击 “批量删除” 按钮可以发现无论如何单击删除按钮浏览器中都没有任何响应打开 Chrome 的控制台后再次单击在 Network 页签中看到当前请求被浏览器识别为跨域请求在控制台中也有相应的 Access-Control-Allow-Origin 错误提示。与此同时还发现后端 8081 实例中控制台有正确的输出内容说明后端的确接收到该请求并予以处理只是响应给浏览器后被浏览器拒绝因此才出现了浏览器无响应的情况。10.4.3 CORS 解决跨域问题针对跨域问题W3C 制定了一个标准即跨域资源共享 (CORS)。CORS 的实现需要浏览器与服务端同时支持才可以不过好在绝大多数主流浏览器支持所以要实现的就是如何让服务端实现该标准也就是如何在代码中配置实现。WebMvc 提供的解决跨域问题的注解是 CrossOrigin它可以标注在需要的 Controller 类或 Handler 方法上标注后即可以实现跨域资源共享。找到UserController并在整个类上标注 CrossOrigin 注解。之后重启工程实例在浏览器上重新单击 “批量删除” 按钮可以发现浏览器成功处理了该响应并弹出提示框证明 CrossOrigin 注解解决跨域问题成功此时观察该请求的响应头时可以发现WebMvc 附加了几个可以让浏览器处理的跨域允许信息。10.4.4 CrossOrigin 的细节1.标注的位置CrossOrigin 可以标注在 Controller 类上也可以标注在 Handler 方法上这种写法比较类似于 RequestMapping。标注在一个Controller 类上则整个 Controller 中标注了 RequestMapping 的方法都支持跨域访问标注在某一个 Handler 方法上则对应的方法支持跨域访问。2.允许跨域的范围跨域是可以指定请求来源的范围的默认情况下 CrossOrigin 的允许跨域范围是 *也就是任意位置如果需要限定允许跨域的范围则可以自行声明。代码提供了一个简单的指定跨域范围的写法用于指定跨域范围的属性是 origins指定后由 http://localhost:8080 发送的请求才允许跨域访问。3.CrossOrigin 做的工作究其根本CrossOrigin 只是一个便捷的解决跨域的方法而已使用原生 Servlet 的 API 也可以完成相同的工作因为解决跨域问题的核心是给响应头中添加一些额外的信息其中最重要的就是上面刚提到的允许跨域的范围也就是响应头中的 Access-Control-Allow-Origin: * 。所以 CrossOrigin 完成的该工作其实就相当于用 HttpServletResponse 执行了一行代码response.addHeader(“Access- Control-Allow-Origin”, “*”);。10.4.5 全局设置跨域最后介绍一个全局设置跨域的方式考虑到每个 Controller 中都需要标注 CrossOrigin 注解会很麻烦WebMvc 提供了一个可以全局设置跨域的扩展点在 WebMvcConfigurer 中有一个 addCorsMappings 方法该方法可以编程式注册跨域允许的映射信息代码提供了一个简单示例这段代码会将当前工程中所有的 GET 和 POST 请求都设置为允许跨域但是实际开发中不建议读者这样做最好是按需配置。ConfigurationpublicclassCrossOriginConfigurationimplementsWebMvcConfigurer{OverridepublicvoidaddCorsMappings(CorsRegistryregistry){registry.addMapping(/*).allowedMethods(GET,POST).allowedOrigins(*).allowCredentials(true);}}
返回列表