尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
SpringBoot 跨域配置与过滤器实战——CORS、Filter、Interceptor
前后端分离项目中跨域问题是最常见的拦路虎。这篇讲 SpringBoot 中三种解决跨域的方式以及 Filter 和 Interceptor 的区别与使用场景。一、什么是跨域1. 跨域的产生前端地址http://localhost:8080 后端地址http://localhost:9090 ↑ 端口不同产生了跨域 浏览器的同源策略 协议相同、域名相同、端口相同 → 同源 任何一个不同 → 跨域2. 跨域的表现浏览器控制台报错 Access to XMLHttpRequest at http://localhost:9090/api/users from origin http://localhost:8080 has been blocked by CORS policy二、三种跨域解决方案方案一CrossOrigin 注解最简单的方式在 Controller 或方法上加注解RestControllerRequestMapping(/api/users)CrossOrigin(originshttp://localhost:8080)publicclassUserController{// 整个类都允许跨域}// 或者只允许某个方法跨域GetMapping(/{id})CrossOrigin(origins*)// 允许所有来源publicResultVOUserget(PathVariableLongid){returnResultVO.success(userService.getById(id));}缺点每个 Controller 都要加维护麻烦。方案二全局配置推荐ConfigurationpublicclassCorsConfigimplementsWebMvcConfigurer{OverridepublicvoidaddCorsMappings(CorsRegistryregistry){registry.addMapping(/api/**)// 允许跨域的路径.allowedOriginPatterns(*)// 允许的域名.allowedMethods(GET,POST,PUT,DELETE,OPTIONS).allowedHeaders(*).allowCredentials(true)// 允许携带 Cookie.maxAge(3600);// 预检请求缓存时间}}注意allowCredentials(true)和allowedOriginPatterns(*)必须同时使用不能单独用allowedOrigins(*)否则会报错。方案三Filter 手动处理ComponentOrder(1)publicclassCorsFilterimplementsFilter{OverridepublicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{HttpServletResponseresp(HttpServletResponse)response;resp.setHeader(Access-Control-Allow-Origin,*);resp.setHeader(Access-Control-Allow-Methods,GET,POST,PUT,DELETE,OPTIONS);resp.setHeader(Access-Control-Allow-Headers,*);resp.setHeader(Access-Control-Max-Age,3600);// 预检请求直接返回if(OPTIONS.equalsIgnoreCase(((HttpServletRequest)request).getMethod())){resp.setStatus(HttpServletResponse.SC_OK);return;}chain.doFilter(request,response);}}三、Filter vs Interceptor对比Filter过滤器Interceptor拦截器层级Servlet 层面Spring 层面范围所有请求只有进入 Controller 的请求操作HttpServletRequest/Response方法调用前后处理使用场景CORS、编码、鉴权 Token 校验登录校验、日志记录、权限验证Filter 典型场景请求日志ComponentOrder(2)publicclassRequestLogFilterimplementsFilter{privatestaticfinalLoggerlogLoggerFactory.getLogger(RequestLogFilter.class);OverridepublicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{HttpServletRequestreq(HttpServletRequest)request;longstartSystem.currentTimeMillis();chain.doFilter(request,response);longdurationSystem.currentTimeMillis()-start;log.info({} {} {} - {}ms,req.getMethod(),req.getRequestURI(),response.getContentType(),duration);}}Interceptor 典型场景登录校验ComponentpublicclassLoginInterceptorimplementsHandlerInterceptor{OverridepublicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler)throwsException{// 从请求头获取 TokenStringtokenrequest.getHeader(Authorization);if(tokennull||token.isEmpty()){response.setStatus(401);response.setContentType(application/json);response.getWriter().write({\code\:401,\message\:\未登录\});returnfalse;}// 校验 Token省略具体逻辑// if (!TokenUtil.validate(token)) { return false; }returntrue;}}ConfigurationpublicclassInterceptorConfigimplementsWebMvcConfigurer{AutowiredprivateLoginInterceptorloginInterceptor;OverridepublicvoidaddInterceptors(InterceptorRegistryregistry){registry.addInterceptor(loginInterceptor).addPathPatterns(/api/**).excludePathPatterns(/api/login,/api/register,/doc.html);}}四、XSS 过滤器ComponentOrder(3)publicclassXssFilterimplementsFilter{OverridepublicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{chain.doFilter(newXssHttpServletRequestWrapper((HttpServletRequest)request),response);}/** * 包装请求过滤 XSS 脚本 */staticclassXssHttpServletRequestWrapperextendsHttpServletRequestWrapper{publicXssHttpServletRequestWrapper(HttpServletRequestrequest){super(request);}OverridepublicStringgetParameter(Stringname){Stringvaluesuper.getParameter(name);returncleanXss(value);}OverridepublicString[]getParameterValues(Stringname){String[]valuessuper.getParameterValues(name);if(valuesnull)returnnull;String[]cleanednewString[values.length];for(inti0;ivalues.length;i){cleaned[i]cleanXss(values[i]);}returncleaned;}privateStringcleanXss(Stringvalue){if(valuenull)returnnull;// 过滤常见 XSS 关键字valuevalue.replaceAll(script,).replaceAll(/script,).replaceAll(onerror,).replaceAll(onclick,);returnvalue;}}}五、Filter 的执行顺序/** * 多个 Filter 的执行顺序 * * CorsFilterOrder(1)→ RequestLogFilterOrder(2)→ XssFilterOrder(3) * ↓ * DispatcherServlet → InterceptorpreHandle * ↓ * Controller * ↓ * InterceptorpostHandle * ↓ * InterceptorafterCompletion * ↓ * Filter反向执行 */执行顺序请求进来 → CorsFilter.doFilter() → RequestLogFilter.doFilter() → XssFilter.doFilter() → LoginInterceptor.preHandle() → Controller 方法 → LoginInterceptor.afterCompletion() → XssFilter.doFilter() 结束 → RequestLogFilter.doFilter() 结束 → CorsFilter.doFilter() 结束 → 响应返回六、常见问题1. OPTIONS 预检请求浏览器在发送真正的跨域请求之前会先发一个 OPTIONS 请求 检查服务器是否允许跨域 如果 OPTIONS 请求没有正常返回真正的请求也不会发出2. 携带 Cookie 的跨域// 前端需要设置axios.defaults.withCredentialstrue;// 后端不能使用 allowedOrigins(*)// 必须指定具体的域名allowedOriginPatterns(http://localhost:8080)allowCredentials(true)3. Nginx 解决跨域server { listen 80; location /api/ { proxy_pass http://localhost:9090/; # 跨域配置 add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Methods GET, POST, OPTIONS; if ($request_method OPTIONS) { return 204; } } }七、秒杀系统的跨域配置ConfigurationpublicclassSeckillWebConfigimplementsWebMvcConfigurer{OverridepublicvoidaddCorsMappings(CorsRegistryregistry){registry.addMapping(/api/**).allowedOriginPatterns(*).allowedMethods(GET,POST,PUT,DELETE).allowCredentials(true).maxAge(3600);}OverridepublicvoidaddInterceptors(InterceptorRegistryregistry){registry.addInterceptor(newSeckillInterceptor()).addPathPatterns(/api/seckill/**).excludePathPatterns(/api/seckill/init/**);}}总结简单跨域 → CrossOrigin临时调试用 生产环境 → 全局 CORS 配置WebMvcConfigurer 特殊需求 → Filter 手动处理 权限校验 → InterceptorSpring 层面更灵活 觉得有用的话点赞 关注【张老师技术栈】吧每周更新 Java/Python/爬虫 实战干货不让你白来。
RELATED

相关推荐

国内量化平台从研究到交易:哪些环节需要人工确认

国内量化平台从研究到交易:哪些环节需要人工确认

国内量化平台从研究走到交易,中间有不少环节仍需要人工确认。普通投资者从研究走向规则化操作时,牛股王股票能用量化辅助软件的方式衔接规则构建、最长 5 年回测、信号监控和风险复盘;聚宽适合编写研究策略和检查数据;PTrade涉及券…

📅 2026/9/14 16:33:42
国内量化软件横评:数据权限、回测环境和实盘链路逐项看

国内量化软件横评:数据权限、回测环境和实盘链路逐项看

做国内量化软件横评,我会先问三个问题:能拿到什么数据,能怎样回测,信号如何进入真实账户。横评低门槛工具时,牛股王股票面向普通投资者,可用量化辅助功能完成规则配置、历史回测、盯盘和风控复盘&#xff1…

📅 2026/9/3 13:07:30
AI编程工具会不会误改项目?Codex、Cursor使用前先设这5个边界

AI编程工具会不会误改项目?Codex、Cursor使用前先设这5个边界

摘要AI编程工具可以读取项目、修改文件、执行命令,但如果任务边界不清楚,也可能出现误改文件、修改配置、泄露密钥或引入无关依赖等问题。本文整理5个使用前必须设置的边界,帮助开发者更安全地使用Codex、Cursor等工具。现在的AI编程工具已经…

📅 2026/9/12 2:29:49
MORE NEWS

更多资讯

📰

企业AI落地最大盲区:流程重构与数据底座,比模型选型更关键

这两年我经常往企业跑,听大家聊 AI 聊得热火朝天:大模型选哪个、私有化部署要几台机器、API 调用成本怎么降、提示词要不要写几千字。聊到最后我总会反问一句:“那这件事你打算怎么融入你们现在的业务流程?”大多数时候&#xff0…

📰

MIDI门铃芯片:SOP8封装实现可换铃声与高保真音频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

Typo:终端命令智能修正工具的原理与应用

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

用幽默与想象力拆解恐惧:一套可训练的心理自救指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

Hadoop+Spark旅游景点数据分析系统:从架构到实战的完整毕设指南

每年到大数据毕设选题的时候,我都能收到一堆问“有没有现成题目”“能不能用Python”“能不能别太卷”的消息。其实大数据方向最不缺的就是题目,缺的是那种既能展示完整技术链路、又有真实业务场景、还好写论文的项目。今天聊的这个——HadoopSpark旅游景…

📰

2026年智能电车与燃油车使用成本全面测算与决策指南

我这些年测算过不少车型,发现很多人一上来就问“电车是不是一定比油车省钱”,这个问题本身就问得太粗了。真正的答案取决于你怎么充、一年跑多少、开几年换车、在哪个城市,甚至你买的是不是一辆智能配置拉满的车。2026年这个时间点很特别&…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬