当前位置: 首页 > news >正文

甘肃定西校园文化设计公司seo综合查询接口

甘肃定西校园文化设计公司,seo综合查询接口,做创新方法工作的网站,推广网站有哪些比较好背景 前段时间帮同事分析了一个跨域问题#xff0c;正好系统分析和整理一下。 1.跨域 理解同源策略是理解跨域的前提。同源策略定义如下#xff1a; 在同一来源的页面和脚本之间进行数据交互时#xff0c;浏览器会默认允许操作#xff0c;而不会造成跨站脚本攻击#x…背景 前段时间帮同事分析了一个跨域问题正好系统分析和整理一下。 1.跨域 理解同源策略是理解跨域的前提。同源策略定义如下 在同一来源的页面和脚本之间进行数据交互时浏览器会默认允许操作而不会造成跨站脚本攻击不同源之间进行限制。 不同源之间形成跨域包括协议、域名、端口。http和httpslocalhost和127.0.0.1也会形成跨域(即使经过域名解析后相同)。 由于浏览器引擎实现了同源策略即对跨域访问进行了限制因此存在跨域问题。 注意注意区分浏览器引擎和V8引擎的区别浏览器引擎包括解析HTML/JS/CSS和渲染等功能而V8只是一个JS解析器因此浏览器中存在跨域问题而基于Chrome-V8的Nodejs中不存在跨域问题。 案例说明 2.浏览器处理跨域步骤 根据请求类型不同浏览器有不同的处理策略可以分为简单请求和复杂请求: 2.1 简单请求 满足以下条件的为简单请求 (1) 方法取值范围GETPOSTHEAD; (2) Context-Type取值范围: text/plain, application/x-www-form-urlencoded, multipart/form-data (3) 不包含自定义头域; 即只能包含HTTP自带的Accept, Accept-Language, Content-Type … 详见: CORS 对于简单请求浏览器会直接向服务器发送请求。 2.2 复杂请求 简单请求之外的HTTP请求为复杂请求。此时浏览器会正式请求之前会先发送一个OPTIONS类型的预检请求。 2.3 跨域请求头域 如果ajax是跨域请求浏览器收到HTTP请求响应后对响应头进行分析——是否支持跨域支持-请求正常否则-抛出异常。 响应头包含以下几个部分 (1) Access-Control-Allow-Origin 指定哪些域可以访问请求的资源, 多个用逗号分开; 取值为file://时表示只允许来自本地文件系统的跨域请求, 而* 表示允许所有源访问。 (2) Access-Control-Allow-Credentials 取值范围有true和false; 表示是否允许客户端使用认证信息如cookies、HTTP身份验证等进行跨域请求。即取值为true时客户端可以携带认证信息如cookies以进行身份验证和个性化等操作。 (3) Access-Control-Allow-Methods 取值范围为HTTP的方法类型如GET和POST指定允许的HTTP请求方法多个使用逗号分隔。 (4) Access-Control-Allow-Headers 这个头域用于指定允许客户端访问的响应头, 多个值用逗号分隔 例如Access-Control-Expose-Headers: X-Custom-Header, Content-Type表示允许客户端访问X-Custom-Header和Content-Type响应头。 上述4个属性是浏览器判断是否跨域的依据。 注意当指定多个Access-Control-Allow-Origin时浏览器会报错如下 Access to XMLHttpRequest at http://localhost:8181/a/b/c from origin http://localhost:8182 has been blocked by CORS policy: The Access-Control-Allow-Origin header contains multiple values *, *, but only one is allowed.2.4 跨域解决方式 2.4.1 前端解决跨域 前端可通过使用JSONP和代理服务器方式解决。如 vue项目中使用Axios实现跨域的原理是代理服务器在vue项目中通常会使用webpack-dev-server作为开发服务器它内置了HTTP代理功能。当Axios发出跨域请求时它会将请求发送到webpack-dev-server的代理服务器上代理服务器将请求转发到目标服务器。在转发过程中代理服务器会处理跨域请求从而绕过浏览器的同源策略限制。 2.4.2 后端-服务器解决跨域 服务端处理跨域问题的核心是在HTTP响应中加入指定的响应头使得浏览器正常校验跨域。 可通过过滤器(Filter)和SpringMVC的拦截器()来实现。 案例1-使用过滤器Filter: Filter可以自定义也可使用开源解决方案 dependencygroupIdcom.thetransactioncompany/groupIdartifactIdcors-filter/artifactIdversion2.9/version /dependency配置并注册到web容器中: filterfilter-nameCORS/filter-namefilter-classcom.thetransactioncompany.cors.CORSFilter/filter-classinit-paramparam-namecors.allowOrigin/param-nameparam-value*/param-value/init-paraminit-paramparam-namecors.supportedMethods/param-nameparam-valueGET, POST, HEAD, PUT, DELETE/param-value/init-paraminit-paramparam-namecors.supportedHeaders/param-nameparam-valueAccept, Origin, X-Requested-With, Content-Type, Last-Modified/param-value/init-paraminit-paramparam-namecors.exposedHeaders/param-nameparam-valueSet-Cookie/param-value/init-paraminit-paramparam-namecors.supportsCredentials/param-nameparam-valuetrue/param-value/init-param /filterfilter-mappingfilter-nameCORS/filter-nameurl-pattern/*/url-pattern /filter-mapping 案例2-使用拦截器 // 定义跨域拦截器 public class CrossInterceptor implements HandlerInterceptor {Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {response.addHeader(Access-Control-Allow-Origin, *);response.addHeader(Access-Control-Allow-Methods, *);response.addHeader(Access-Control-Max-Age, 100);response.addHeader(Access-Control-Allow-Headers, Content-Type);response.addHeader(Access-Control-Allow-Credentials, false);return true;} }// 注册拦截器 Configuration public class MyInterceptorConfig implements WebMvcConfigurer {Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new CrossInterceptor());} }相对于过滤器和拦截器SpringMVC提供了颗粒度更小的解决方案使用CrossOrigin注解即可解决跨域问题。 如下所示 RestController RequestMapping(/api/crossDemo) public class CrossController {CrossOrigin(origins *, maxAge 3600)RequestMapping(value /put, method RequestMethod.PUT)public String put() {return success;} }CrossOrigin可注解在方法上对方法生效也可作用在类上对类中所有方法生效当类和方法都存在CrossOrigin注解时方法上的注解会覆盖类上的注解。 3.CrossOrigin原理介绍 CrossOrigin注解本质上是对SpringMVC的调用链添加一个拦截器在拦截器中对HTTP的响应头进行跨域设置。 3.1 CrossOrigin注解 CrossOrigin注解包含以下属性: [1] value和origins属性: String[]类型 指定允许请求源列表; 一般设置为*表示对所有的网址开放。与Access-Control-Allow-Origin头域保持一致。 [2] allowedHeaders属性: String[]类型请求中允许的请求头列表。如果设置成“*”则表示允许所有的请求头。 [3] exposedHeaders属性: String[]类型CrossOrigin注解的exposedHeaders属性用于指定允许暴露的响应头列表。这个属性主要用于控制客户端如浏览器可以访问哪些响应头。如果设置成“*”则表示允许暴露所有的响应头。 例如假设我们有一个API接口需要暴露响应头Content-Length给客户端可以这样设置 CrossOrigin(origins *, allowedHeaders *, exposedHeaders Content-Length)在这个例子中我们允许来自http://example.com的请求访问我们的API并允许请求头Content-Type。同时我们指定了响应头Content-Length可以被客户端访问。在实际的CORS请求中响应头Content-Length将被存储在Access-Control-Expose-Headers列表中客户端可以通过这个头获取Content-Length信息。 默认情况下暴露的响应头有Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果需要暴露其他的响应头需要在CrossOrigin注解中显式指定。 [4] methods属性: RequestMethod[]类型methods属性用于指定允许的HTTP方法。它是一个字符串数组表示允许跨域请求的HTTP方法列表。这个属性主要用于控制哪些HTTP请求方法可以被客户端如浏览器使用。与Access-Control-Allow-Methods头域保持一致。如果API接口只允许GET和POST方法进行跨域请求可以按如下方式进行设置 CrossOrigin(origins *, allowedHeaders *, methods GET,POST)[5] allowCredentials属性: String类型与Access-Control-Allow-Credentials头域保持一致表示是否允许携带认证信息如cookies、HTTP身份验证等进行跨域请求。 [6] maxAge属性: long类型 预检请求的有效期(单位: 秒)有效期内不必再次发送预检请求默认是-1。 当maxAge值为-1时表示预检请求没有有效期限制。即浏览器接收到预检响应后无论经过多长时间只要浏览器与服务器之间的连接保持打开状态都不需要再次发送预检请求。 3.2 项目初始化 RequestMappingHandlerMapping类实现了InitializingBean接口在初始化阶段会调用afterPropertiesSet钩子方法: public void afterPropertiesSet() {initHandlerMethods(); }initHandlerMethods()方法核心是调用register方法进行Controller接口url的注册该过程会同时设置跨域信息 public void register(T mapping, Object handler, Method method) {// register url 和 method关系CorsConfiguration corsConfig initCorsConfiguration(handler, method, mapping);if (corsConfig ! null) {this.corsLookup.put(handlerMethod, corsConfig);}// ... }通过initCorsConfiguration方法获取跨域配置保存在内存(corsLookup属性)中。 initCorsConfiguration方法逻辑如下 Override protected CorsConfiguration initCorsConfiguration(Object handler, Method method, RequestMappingInfo mappingInfo) {HandlerMethod handlerMethod createHandlerMethod(handler, method);Class? beanType handlerMethod.getBeanType();// 从Controller类上获取CrossOrigin注解CrossOrigin typeAnnotation AnnotatedElementUtils.findMergedAnnotation(beanType, CrossOrigin.class);// 从接口方法上获取CrossOrigin注解CrossOrigin methodAnnotation AnnotatedElementUtils.findMergedAnnotation(method, CrossOrigin.class);// 没有注解表示不进行跨域处理if (typeAnnotation null methodAnnotation null) {return null;}CorsConfiguration config new CorsConfiguration();// 先根据类的注解信息进行构造再使用方法注解信息覆盖因此优先级方法高于类updateCorsConfig(config, typeAnnotation);updateCorsConfig(config, methodAnnotation);if (CollectionUtils.isEmpty(config.getAllowedMethods())) {for (RequestMethod allowedMethod : mappingInfo.getMethodsCondition().getMethods()) {config.addAllowedMethod(allowedMethod.name());}}// 默认设置return config.applyPermitDefaultValues(); }Note: 通过注解未设置时applyPermitDefaultValues方法进行默认设置 allowedOrigins跨域源设置为*, allowedMethods和resolvedMethods设置为GET、HEAD、POSTallowedHeaders设置为*;maxAge设为为1800L, 即30分钟。 3.3 HTTP接口被调用 当请求进入DispatcherServlet的doDispatch方法中 protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {//...// Determine handler adapter for the current request.HandlerAdapter ha getHandlerAdapter(mappedHandler.getHandler());//...// 调用拦截器的preHandle方法if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}//...// 调用目标Controller接口mv ha.handle(processedRequest, response, mappedHandler.getHandler());//... }getHandlerAdapter(mappedHandler.getHandler())根据被调用的接口获取HandlerAdapter对象该对象包含一个调用链CrossOrigin注解关联的拦截器添加在该链路中。 构造调用链的逻辑如下所示: public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {Object handler getHandlerInternal(request);// 根据被调用的Controller接口构造执行链 HandlerExecutionChain executionChain getHandlerExecutionChain(handler, request);// 向执行链中添加跨域拦截器if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {CorsConfiguration config (this.corsConfigurationSource ! null ? this.corsConfigurationSource.getCorsConfiguration(request) : null);// 从内存中获取跨域-拦截器对象上一节中的保存为了这里的获取CorsConfiguration handlerConfig getCorsConfiguration(handler, request);config (config ! null ? config.combine(handlerConfig) : handlerConfig);executionChain getCorsHandlerExecutionChain(request, executionChain, config);}return executionChain; }至此CrossOrigin注解的实现原理已梳理完成。 注意Spring在不同版本实现有区别(最近定位问题时发现一个因版本升级导致的问题-促使我发现这个问题): 5.2.8.RELEASE中: protected HandlerExecutionChain getCorsHandlerExecutionChain(HttpServletRequest request, HandlerExecutionChain chain, Nullable CorsConfiguration config) {if (CorsUtils.isPreFlightRequest(request)) {HandlerInterceptor[] interceptors chain.getInterceptors();chain new HandlerExecutionChain(new PreFlightHandler(config), interceptors);} else {chain.addInterceptor(0, new CorsInterceptor(config));}return chain; }4.3.20.RELEASE版本中: protected HandlerExecutionChain getCorsHandlerExecutionChain(HttpServletRequest request, HandlerExecutionChain chain, CorsConfiguration config) {if (CorsUtils.isPreFlightRequest(request)) {HandlerInterceptor[] interceptors chain.getInterceptors();chain new HandlerExecutionChain(new PreFlightHandler(config), interceptors);} else {chain.addInterceptor(new CorsInterceptor(config));}return chain; }区别在于5.2.8.RELEASE版本将跨域拦截器CorsInterceptor放在了拦截器首部而4.3.20.RELEASE将CorsInterceptor加在了拦截器尾部。 执行顺序不同业务上可能会引入问题。
http://www.dnsts.com.cn/news/211868.html

相关文章:

  • 长沙在线建站模板产品设计方案怎么写
  • 个人网站如何做流量网站所有权查询
  • 网站开发如何跟客户沟通需求用word怎么做首页网站
  • 公司做网站好网站建设平台市场
  • 做平面图片的网站传媒公司网站建设方案
  • 有哪些做室内设计好用的网站有哪些百度推广网页制作
  • 上海八号桥 网站建设文成网站建设
  • 门户网站开发费需入无形资产做美妆网站名称
  • 手机网站开发 html5长尾关键词挖掘爱站工具
  • 西安模板网站重庆网站建设及推广公司
  • 金水郑州网站建设广州做网站建设的公司
  • 织梦旅游网站wordpress静态网址
  • wordpress pin宁波seo快速优化教程
  • 做编程的+网站快递网站制作
  • 文章类网站后台建设厅国网查询网站
  • 天津企业网站专业订制摄影网站制作
  • 厦门市住房和建设局网站网站备案查询中心
  • 怎样做无水印视频网站荆州网站建设荆州
  • 自己想学做博客网站吗注册会计师协会
  • 网站管理员密码忘记了个人网页设计的主要内容和要求
  • 青岛中小微企业互联网站建设补贴wordpress p 收录
  • 有特点的个人网站建设网站盈利2015
  • 成品网站是什么意思建设网站e护航下载
  • 网站建设中图片多少钱做企业网站的意义
  • 无锡网站建设唯唯网络深圳网站建设哪家便宜
  • 淘宝移动网站建设设计中国展
  • php建设网站教程情感网站seo
  • 如何在电商上购物网站购物网站的功能板块
  • 肃宁网站建设价格wordpress 社交按钮
  • 深圳公司网站备案需要什么资料家装设计师个人简介