javaEE WebServlet、SpringWebMVC、SpringBoot实现跨域访问的4种方式及优先级,nginx配置跨域
茅坑的小石头 2024-08-14 08:33:01 阅读 64
文章目录
1. 前置知识2. 原理和解决方案总结2.1. 跨域不通过原理流程图2.2. 实现原理:添加以下http响应头2.3. 四种跨域实现方式及优先级(从高到低)
3. 具体实现代码3.1. 跨域全局配置方式-Filter(全适用)3.2. 跨域全局配置方式-SpringMvc3.3. 跨域单个配置方式-WebServlet3.4. 跨域单个配置方式-SpringMvc
4.非java实现方式4.1. nginx代理
9. 参考文章
1. 前置知识
【尚硅谷】【视频】【B站】禹神:一小时彻底搞懂跨域&解决方案【尚硅谷】【笔记】【CSDN】禹神:彻底搞懂前端跨域&解决方案
2. 原理和解决方案总结
2.1. 跨域不通过原理流程图
2.2. 实现原理:添加以下http响应头
序号 | 响应头 | 含义 |
---|---|---|
1 | Access-Control-Allow-Origin | 允许的源 |
2 | Access-Control-Allow-Methods | 允许的方法 |
3 | Access-Control-Allow-Headers | 允许的自定义头 |
4 | Access-Control-Max-Age | 预检请求的结果缓存时间(可选) |
2.3. 四种跨域实现方式及优先级(从高到低)
跨域全局配置方式-Filter(全适用): 重写 Filter.doFilter(),设置 res.setHeader(“Access-Control-Allow-Origin”, “*”) 等响应头参数跨域全局配置方式-SpringMvc : 重写 WebMvcConfigurer.addCorsMappings(),设置 registry.addMapping(“/**”).allowedOrigins(“*”)等响应头参数(只对SpringMvc写法生效,对原生Servlet不生效)跨域单个配置方式-WebServlet: 设置 res.addHeader(“Access-Control-Allow-Origin”, “*”) 等响应头参数跨域单个配置方式-SpringMvc : 添加 @CrossOrigin注解,设置origins等响应头参数(只对SpringMvc写法生效,对原生Servlet不生效)
3. 具体实现代码
gitee源码
3.1. 跨域全局配置方式-Filter(全适用)
重写<code>Filter.doFilter(),设置 res.setHeader("Access-Control-Allow-Origin", "*")
等响应头参数
/** 1.跨域全局配置方式-Filter(全适用) */
@Configuration
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.setHeader("Access-Control-Allow-Origin", req.getHeader("Origin")); //【跨域配置】[必需] 允许请求源 :默认值 无,配置"*"允许所有。
// 如果是复杂请求的预检请求(判断逻辑同SpringMvc),设置以下响应头,且没必要执行其它过滤器链 chain.doFilter(request, response);
if (req.getMethod().equalsIgnoreCase("OPTIONS") && !ObjUtil.hasNull(req.getHeader("Origin"), req.getHeader("Access-Control-Request-Method"))) {
res.setHeader("Access-Control-Allow-Methods", req.getHeader("Access-Control-Request-Method")); //【跨域配置】[有复杂请求方法时必需] 允许请求方法:默认值 无,配置 "*",允许所有
res.setHeader("Access-Control-Allow-Headers", req.getHeader("Access-Control-Request-Headers")); //【跨域配置】[有复杂请求头时必需] 允许请求头 : 默认值 无,配置 "*",允许所有
res.setHeader("Access-Control-Max-Age", "5"); //【跨域配置】[非必需] 预检缓存时长: 默认值 依赖客户端。EDGE浏览器默认值为3秒。【注意浏览器不要禁用缓存,否则不生效】
return;
}
}
}
3.2. 跨域全局配置方式-SpringMvc
重写 WebMvcConfigurer.addCorsMappings(),设置 registry.addMapping(“/**”).allowedOrigins(“*”)等响应头参数(只对SpringMvc写法生效,对原生Servlet不生效)
/** 2.跨域全局配置方式-SpringMvc */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 适配@RequestMapping。 (例如:/ajax/** 开头的)
// 下面几个参数,不配置,会使用默认值。origins 和 originPatterns取并集
.allowedOrigins("*") //【跨域配置】[必需] 允许请求源:默认值为"*",即允许所有。相当于res.setHeader("Access-Control-Allow-Origin", )
.allowedOriginPatterns("*") //【跨域配置】[必需] 允许请求源:默认值为"*",即允许所有。相当于res.setHeader("Access-Control-Allow-Origin", )
.allowedMethods("*") //【跨域配置】[有复杂请求方法时必需] 允许请求方法:默认值为GET,POST,HEAD。相当于res.setHeader("Access-Control-Allow-Methods", )
.allowedHeaders("*") //【跨域配置】[有复杂请求头时必需] 允许请求头 :默认值为"*",即允许所有。相当于res.setHeader("Access-Control-Allow-Headers", )
.maxAge(1800); //【跨域配置】[非必需] 预检缓存时长:默认值 1800秒。小于等于0时缓存无效【注意浏览器不要禁用缓存,否则不生效】。相当于res.setHeader("Access-Control-Max-Age", )
}
}
3.3. 跨域单个配置方式-WebServlet
设置 res.addHeader(“Access-Control-Allow-Origin”, “*”) 等响应头参数
/** 3.跨域单个配置方式-WebServlet */
@Slf4j
@WebServlet(name = "ajax", value = { "/ajax/WebServlet", "/ajax/WebServlet/"})
public class AjaxWebServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse res) throws IOException {
log.warn("method==【{}】, name==【{}】, header.origin==【{}】, Access-Control-Request-Method==【{}】, Access-Control-Request-Headers==【{}】", req.getMethod(), req.getParameter("name"), req.getHeader("Origin"), req.getHeader("Access-Control-Request-Method"), req.getHeader("Access-Control-Request-Headers"));
res.setHeader("Access-Control-Allow-Origin", "*"); //【跨域配置】[必需] 允许请求源 :默认值 无,配置"*"允许所有。
res.setHeader("Access-Control-Allow-Methods", "*"); //【跨域配置】[有复杂请求方法时必需] 允许请求方法:默认值 无,配置 "*",允许所有
res.setHeader("Access-Control-Allow-Headers", "*"); //【跨域配置】[有复杂请求头时必需] 允许请求头 : 默认值 无,配置 "*",允许所有
res.setHeader("Access-Control-Max-Age", "1800"); //【跨域配置】[非必需] 预检缓存时长: 默认值 依赖客户端。EDGE浏览器默认值为3秒。【注意浏览器不要禁用缓存,否则不生效】
res.getWriter().write(DateUtil.now() + "@" + req.getMethod());
}
}
3.4. 跨域单个配置方式-SpringMvc
添加 @CrossOrigin注解,设置origins等响应头参数(只对SpringMvc写法生效,对原生Servlet不生效)
/* 4.跨域单个配置方式-SpringMvc */
@Slf4j
@RestController
@RequestMapping("/ajax")
public class AjaxController {
@CrossOrigin(
// origins 和 originPatterns取并集。【注意】此处配置与下面的res.setHeader()功能相同,优先级较低。二选其一即可
origins = { "*"}, //【跨域配置】[必需] 允许请求源 :默认值为"*",即允许所有。相当于res.setHeader("Access-Control-Allow-Origin", )
originPatterns = { "*"}, //【跨域配置】[必需] 允许请求源 :默认值为"*",即允许所有。相当于res.setHeader("Access-Control-Allow-Origin", )
methods = { }, //【跨域配置】[有复杂请求方法时必需] 允许请求方法:默认值为(优先以@RequestMapping的method属性为准,如果没有指定则默认为"GET,POST,HEAD)。相当于res.setHeader("Access-Control-Allow-Methods", )
allowedHeaders = { "*"}, //【跨域配置】[有复杂请求头时必需] 允许请求头 :默认值为"*",即允许所有。相当于res.setHeader("Access-Control-Allow-Headers", )
maxAge = 1800 //【跨域配置】[非必需] 预检缓存时长:默认值 1800秒。小于等于0时缓存无效【注意浏览器不要禁用缓存,否则不生效】 。相当于res.setHeader("Access-Control-Max-Age", )
)
@RequestMapping(value = "/CrossOrigin", method = { RequestMethod.GET, RequestMethod.PUT})
@SneakyThrows
void ajax(HttpServletRequest req, HttpServletResponse res) {
log.warn("method==【{}】, name==【{}】, header.origin==【{}】, Access-Control-Request-Method==【{}】, Access-Control-Request-Headers==【{}】", req.getMethod(), req.getParameter("name"), req.getHeader("Origin"), req.getHeader("Access-Control-Request-Method"), req.getHeader("Access-Control-Request-Headers"));
res.getWriter().write(DateUtil.now() + "@" + req.getMethod());
}
}
4.非java实现方式
4.1. nginx代理
优点:不用侵入java代码
配置nginx反向代理。在配置文件nginx.conf
的http
中添加一个server
将AJAX
请求通过nginx
转发。本例中,将AJAX
请求发给58080
端口,然后转发给8080
端口
server {
listen 58080;
server_name localhost;
location / {
proxy_pass http://localhost:8080;
# 增加响应头
add_header Access-Control-Allow-Origin "*"; # 【跨域配置】[必需] 允许请求源 :默认值 无,配置"*"允许所有。
if ($request_method = 'OPTIONS') { # 如果是复杂请求的预检请求(参考SpringMvc,最好同时判断请求头Origin、Access-Control-Request-Method都不为null,略),设置以下响应头,且没必要透传,直接返回
add_header Access-Control-Allow-Origin "*"; # 【跨域配置】[必需] 允许请求源 :默认值 无,配置"*"允许所有。
add_header Access-Control-Allow-Methods "*"; # 【跨域配置】[有复杂请求方法时必需] 允许请求方法:默认值 无,配置 "*",允许所有
add_header Access-Control-Allow-Headers "*"; # 【跨域配置】[有复杂请求头时必需] 允许请求头 : 默认值 无,配置 "*",允许所有
add_header Access-Control-Max-Age "5"; # 【跨域配置】[非必需] 预检缓存时长: 默认值 依赖客户端。EDGE浏览器默认值为3秒。【注意浏览器不要禁用缓存,否则不生效】
return 204;
}
}
}
9. 参考文章
@CrossOrigin详细参数说明SpringBoot处理跨域请求的四种方法
下一篇: uniapp前端实现微信支付(小程序、公众号H5、app)
本文标签
javaEE WebServlet、SpringWebMVC、SpringBoot实现跨域访问的4种方式及优先级 nginx配置跨域
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。