电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

Spring @CrossOrigin 注解原理實現

瀏覽:47日期:2023-08-28 16:39:50

現實開發中,我們難免遇到跨域問題,以前筆者只知道jsonp這種解決方式,后面聽說spring只要加入@CrossOrigin即可解決跨域問題。本著好奇的心里,筆者看了下@CrossOrigin 作用原理,寫下這篇博客。

先說原理:其實很簡單,就是利用spring的攔截器實現往response里添加 Access-Control-Allow-Origin等響應頭信息,我們可以看下spring是怎么做的

注:這里使用的spring版本為5.0.6

我們可以先往RequestMappingHandlerMapping 的initCorsConfiguration方法打一個斷點,發現方法調用情況如下

Spring @CrossOrigin 注解原理實現

如果controller在類上標了@CrossOrigin或在方法上標了@CrossOrigin注解,則spring 在記錄mapper映射時會記錄對應跨域請求映射,代碼如下

RequestMappingHandlerMappingprotected CorsConfiguration initCorsConfiguration(Object handler, Method method, RequestMappingInfo mappingInfo) { HandlerMethod handlerMethod = createHandlerMethod(handler, method); Class<?> beanType = handlerMethod.getBeanType(); //獲取handler上的CrossOrigin 注解 CrossOrigin typeAnnotation = AnnotatedElementUtils.findMergedAnnotation(beanType, CrossOrigin.class); //獲取handler 方法上的CrossOrigin 注解 CrossOrigin methodAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, CrossOrigin.class); if (typeAnnotation == null && methodAnnotation == null) { //如果類上和方法都沒標CrossOrigin 注解,則返回一個null return null; } //構建一個CorsConfiguration 并返回 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(); }

將結果返回到了AbstractHandlerMethodMapping#register,主要代碼如下

CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping); if (corsConfig != null) {//會保存handlerMethod處理跨域請求的配置 this.corsLookup.put(handlerMethod, corsConfig); }

當一個跨域請求過來時,spring在獲取handler時會判斷這個請求是否是一個跨域請求,如果是,則會返回一個可以處理跨域的handler

AbstractHandlerMapping#getHandler HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); //如果是一個跨域請求if (CorsUtils.isCorsRequest(request)) { //拿到跨域的全局配置 CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request); //拿到hander的跨域配置 CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig); //處理跨域(即往響應頭添加Access-Control-Allow-Origin信息等),并返回對應的handler對象 executionChain = getCorsHandlerExecutionChain(request, executionChain, config); }

我們可以看下如何判定一個請求是一個跨域請求,

public static boolean isCorsRequest(HttpServletRequest request) {//判定請求頭是否有Origin 屬性即可 return (request.getHeader(HttpHeaders.ORIGIN) != null); }

再看下getCorsHandlerExecutionChain 是如何獲取一個handler

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(new CorsInterceptor(config)); } return chain; }

也就是在調用目標方法前會先調用CorsInterceptor#preHandle,我們觀察得到其也是調用了corsProcessor.processRequest方法,我們往這里打個斷點

processRequest方法的主要邏輯如下

public boolean processRequest(@Nullable CorsConfiguration config, HttpServletRequest request, HttpServletResponse response) throws IOException { //.... //調用了自身的handleInternal方法 return handleInternal(serverRequest, serverResponse, config, preFlightRequest); }protected boolean handleInternal(ServerHttpRequest request, ServerHttpResponse response, CorsConfiguration config, boolean preFlightRequest) throws IOException { String requestOrigin = request.getHeaders().getOrigin(); String allowOrigin = checkOrigin(config, requestOrigin); HttpHeaders responseHeaders = response.getHeaders(); responseHeaders.addAll(HttpHeaders.VARY, Arrays.asList(HttpHeaders.ORIGIN, HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS)); if (allowOrigin == null) { logger.debug('Rejecting CORS request because ’' + requestOrigin + '’ origin is not allowed'); rejectRequest(response); return false; } HttpMethod requestMethod = getMethodToUse(request, preFlightRequest); List<HttpMethod> allowMethods = checkMethods(config, requestMethod); if (allowMethods == null) { logger.debug('Rejecting CORS request because ’' + requestMethod + '’ request method is not allowed'); rejectRequest(response); return false; } List<String> requestHeaders = getHeadersToUse(request, preFlightRequest); List<String> allowHeaders = checkHeaders(config, requestHeaders); if (preFlightRequest && allowHeaders == null) { logger.debug('Rejecting CORS request because ’' + requestHeaders + '’ request headers are not allowed'); rejectRequest(response); return false; } //設置響應頭 responseHeaders.setAccessControlAllowOrigin(allowOrigin); if (preFlightRequest) { responseHeaders.setAccessControlAllowMethods(allowMethods); } if (preFlightRequest && !allowHeaders.isEmpty()) { responseHeaders.setAccessControlAllowHeaders(allowHeaders); } if (!CollectionUtils.isEmpty(config.getExposedHeaders())) { responseHeaders.setAccessControlExposeHeaders(config.getExposedHeaders()); } if (Boolean.TRUE.equals(config.getAllowCredentials())) { responseHeaders.setAccessControlAllowCredentials(true); } if (preFlightRequest && config.getMaxAge() != null) { responseHeaders.setAccessControlMaxAge(config.getMaxAge()); } //刷新 response.flush(); return true; }

至此@CrossOrigin的使命就完成了,說白了就是用攔截器給response添加響應頭信息而已

到此這篇關于Spring @CrossOrigin 注解原理實現的文章就介紹到這了,更多相關Spring @CrossOrigin 注解內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Spring
相關文章:
主站蜘蛛池模板: 儋州在线-儋州招聘找工作、找房子、找对象,儋州综合生活信息门户! | 奥运星-汽车性能网评-提供个性化汽车资讯 | 桁架楼承板-钢筋桁架楼承板-江苏众力达钢筋楼承板厂 | 华夏医界网_民营医疗产业信息平台_民营医院营销管理培训 | 达利园物流科技集团-| 耐火浇注料价格-高强高铝-刚玉碳化硅耐磨浇注料厂家【直销】 | 99文库_实习生实用的范文资料文库站 | 采暖炉_取暖炉_生物质颗粒锅炉_颗粒壁炉_厂家加盟批发_烟台蓝澳采暖设备有限公司 | 深圳品牌设计公司-LOGO设计公司-VI设计公司-未壳创意 | PSI渗透压仪,TPS酸度计,美国CHAI PCR仪,渗透压仪厂家_价格,微生物快速检测仪-华泰和合(北京)商贸有限公司 | 压装机-卧式轴承轮轴数控伺服压装机厂家[铭泽机械] | 郑州宣传片拍摄-TVC广告片拍摄-微电影短视频制作-河南优柿文化传媒有限公司 | 玉米深加工机械,玉米加工设备,玉米加工机械等玉米深加工设备制造商-河南成立粮油机械有限公司 | 北京律师事务所_房屋拆迁律师_24小时免费法律咨询_云合专业律师网 | 电脑刺绣_绣花厂家_绣花章仔_织唛厂家-[源欣刺绣]潮牌刺绣打版定制绣花加工厂家 | 房车价格_依维柯/大通/东风御风/福特全顺/江铃图片_云梯搬家车厂家-程力专用汽车股份有限公司 | 辐射色度计-字符亮度测试-反射式膜厚仪-苏州瑞格谱光电科技有限公司 | 压接机|高精度压接机|手动压接机|昆明可耐特科技有限公司[官网] 胶泥瓷砖胶,轻质粉刷石膏,嵌缝石膏厂家,腻子粉批发,永康家德兴,永康市家德兴建材厂 | 长沙广告公司|长沙广告制作设计|长沙led灯箱招牌制作找望城湖南锦蓝广告装饰工程有限公司 | 北京网站建设公司_北京网站制作公司_北京网站设计公司-北京爱品特网站建站公司 | 地源热泵一体机,地源热泵厂家-淄博汇能环保设备有限公司 | 广州展览制作工厂—[优简]直营展台制作工厂_展会搭建资质齐全 | 南京欧陆电气股份有限公司-风力发电机官网 | 无线遥控更衣吊篮_IC卡更衣吊篮_电动更衣吊篮配件_煤矿更衣吊篮-力得电子 | 菏泽知彼网络科技有限公司 | 闪电优家-卫生间防水补漏_酒店漏水渗水维修_防水堵漏公司 | 智慧钢琴-电钢琴-便携钢琴-数码钢琴-深圳市特伦斯乐器有限公司 | 电力测功机,电涡流测功机,磁粉制动器,南通远辰曳引机测试台 | 聚天冬氨酸,亚氨基二琥珀酸四钠,PASP,IDS - 远联化工 | 山东led显示屏,山东led全彩显示屏,山东LED小间距屏,临沂全彩电子屏-山东亚泰视讯传媒有限公司 | 不锈钢管件(不锈钢弯头,不锈钢三通,不锈钢大小头),不锈钢法兰「厂家」-浙江志通管阀 | 换链神器官网-友情链接交换、购买交易于一体的站长平台 | 石英砂矿石色选机_履带辣椒色选机_X光异物检测机-合肥幼狮光电科技 | 雷冲击高压发生器-水内冷直流高压发生器-串联谐振分压器-武汉特高压电力科技有限公司 | 对照品_中药对照品_标准品_对照药材_「格利普」高纯中药标准品厂家-成都格利普生物科技有限公司 澳门精准正版免费大全,2025新澳门全年免费,新澳天天开奖免费资料大全最新,新澳2025今晚开奖资料,新澳马今天最快最新图库 | 高压微雾加湿器_工业加湿器_温室喷雾-昌润空气净化设备 | 皮带机_移动皮带机_大倾角皮带机_皮带机厂家 - 新乡市国盛机械设备有限公司 | 智能风向风速仪,风速告警仪,数字温湿仪,综合气象仪(气象五要素)-上海风云气象仪器有限公司 | 北京乾茂兴业科技发展有限公司| 精益专家 - 设备管理软件|HSE管理系统|设备管理系统|EHS安全管理系统 | 超声波_清洗机_超声波清洗机专业生产厂家-深圳市好顺超声设备有限公司 |