java spring 处理跨域

❤️弱水三千,只取一瓢饮❤️
🤞你好啊,我是小酥肉,欢迎阅读本博客👌

跨域相关知识:

本文专注于后端如何处理跨域

注意:我使用的springboot版本为2.7.x,servelt容器为tomcat 9.0.95

http请求在到达spring发生了什么

在这里插入图片描述

1)浏览器向后端发起一个http请求
2)tomcat用socket监听接收,并用io流将http请求转换为Servelt(封装Servelt)
3)Servlet容器管理该Servlet,并交付给spring MVC
4)spring MVC用dispatchServelt将该Servlet转发到对应的Controller,执行业务逻辑
5)返回响应,原路返回。(这里省略了response)

所以处理跨域就有了不同颗粒度/作用域

常见方案

在这里插入图片描述

下面是几种常见的跨域处理方案(后端)(分别对应图中1234):

添加过滤器 filter

在Servelt容器层添加filter,这一步可以在请求刚经过socket,来到容器时处理跨域。

@Component
public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "36000000");
//        response.setHeader("Access-Control-Allow-Headers", "content-type,Authorization");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        filterChain.doFilter(servletRequest, servletResponse);
    }
}

特点:servlet刚进入容器时进行跨域处理,由servelt容器(如tomcat)掌控

webMvcConfigure全局配置

当请求到达spring mvc后,我们可以通过一个配置类进行cors相关的配置

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // 覆盖所有请求
        registry.addMapping("/**")
                // 允许发送 Cookie
                .allowCredentials(true)
                // 放行哪些域名(必须用 patterns,否则 * 会和 allowCredentials 冲突)
                .allowedOriginPatterns("*")
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                .allowedHeaders("*")
                .exposedHeaders("*");
    }
}

特点:细化到mvc框架,应用程序级别的配置,更适合java宝宝体质

添加拦截器Incerpeter

当然我们可以对dispatchServelt转发到controller之间加一层拦截器,它将对应路径(由你配置)的请求拦截,并提供preHanlder对其操作

// 设置跨域拦截器
@Component
public class YourInterceptor implements HandlerInterceptor {


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS");
        response.setHeader("Access-Control-Max-Age", "86400");
        response.setHeader("Access-Control-Allow-Headers", "*");


        // 如果是OPTIONS则结束请求(预检)
        if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
            response.setStatus(HttpStatus.NO_CONTENT.value());
            return false;
        }


        return true;
    }
}

然后把YourInterceptor添加一些匹配路径

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {


    @Resource
    private YourInterceptor yourInterceptor;


    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 跨域拦截器需放在最上面
        registry.addInterceptor(yourInterceptor).addPathPatterns("/**");
        // 校验token的拦截器
        //todo 添加其他的拦截器
        //registry.addInterceptor(yourInterceptor).addPathPatterns("/admin/**");
    }
}

特点:配合WebMvcConfigure全局配置灵活配置,并且由mvc框架掌控

由mvc框架掌控意味着:可以在WebMvcConfigure配置中引入IOC容器的bean。比如上面的@Resource
filter则不行,因为Servelt容器层的东西无法引入bean(跨应用)

@CrossOrigin注解

下面是CrossOrigin的源码

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CrossOrigin

该注解直接注解在方法/类上,可以给某个controller,甚至给某个restful 端点加来实现跨域,但一般跨域属于应用级别操作,这样也可以实现

总结

  • 当请求违反了浏览器同源策略,会印发跨域
  • 解决跨域的方式就是添加对应请求头(由cors标准规定的请求头),一般是后端处理
  • 可以在servelt容器层处理跨域(filter)
  • 也可以在spring mvc层处理跨域(WebMvcConfigure全局配置,拦截器,@CrossOrigin),可以根据自己的需求确定颗粒度
  • filter不可以用bean,而mvc框架的配置则可以(WebMvcConfigure)

注意:跨域的方式还有很多。
比如网关层:cloud gataway,nginx
前端iframe配置,代理跨域
这里的解决方案就是java开发者应该怎么做

❤️弱水三千,只取一瓢饮❤️
🤞我是小酥肉 ,喜欢简单 ,期待您的留言👌

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程就是n踢r

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值