什么是CORS

跨域(CORS)请求:同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指 "协议+域名+端口" 三者相同, 不同源则跨域。

如果还想了解更多,下面这两个文档更加详细的介绍了CORS

CORS 参考链接https://developer.mozilla.org/zh-CN/docs/Glossary/CORS

关于HTTP请求分类参考https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS


SpringBoot 全局配置CORS

添加一个 WebMvc 的配置类,在没有过滤器和拦截器的情况下是ok了。

我这里还配置了一个拦截器,HTTP的预检请求会经过拦截器,我就直接在拦截器里面对预检请求进行处理。(如果配置了过滤器可以在过滤器中进行处理,因为过滤器比拦截器更早经过)

package com.pro.config;

import com.pro.interceptor.BaseInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /**
* 扩展 Web MVC
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer { private static final String[] whiteList = {"/admin/login", "/admin/logout"}; @Autowired
BaseInterceptor baseInterceptor; /**
* 配置拦截器
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(baseInterceptor).excludePathPatterns(whiteList);
} /**
* 配置跨域请求
* @param registry
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
//设置允许跨域请求的域名
.allowedOriginPatterns("*")
// 设置允许请求方式
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD")
// 是否允许证书(cookies)
.allowCredentials(true)
// 预请求的结果能被缓存多久
.maxAge(3600)
// 设置允许的请求头
.allowedHeaders("*");
}
}

拦截器处理预检请求

直接在拦截器里面对预检请求进行处理,处理方法就是这个方法 responseCors

核心处理逻辑

/**
* 请求方法执行之前
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 在进入这个拦截器之前,对跨域提供支持
if (responseCors(response, request)) {
return false;
}
return true;
} /**
* 在进入这个拦截器之前, 对跨域提供支持
* @param response
* @param request
* @return
*/
private boolean responseCors(HttpServletResponse response, HttpServletRequest request) {
// 判断是否是预检请求
if (RequestMethod.OPTIONS.name().equals(request.getMethod())) {
response.setHeader("Cache-Control","no-cache");
response.setHeader("Access-control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");
response.setHeader("Access-Control-Allow-Headers", "*");
// 跨域时会首先发送一个OPTIONS请求,这里我们给OPTIONS请求直接返回正常状态
response.setStatus(HttpStatus.OK.value());
return true;
}
return false;
}

完整拦截器代码

package com.pro.interceptor;

import com.pro.constant.ErrorConstant;
import com.pro.utils.*;
import com.pro.vo.user.UserInfoVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; /**
* 自定义拦截器
*/
@Component
public class BaseInterceptor implements HandlerInterceptor { private static final Logger LOGGER = LoggerFactory.getLogger(BaseInterceptor.class);
private static final String USER_AGENT = "user-agent"; // 后台管理请求接口白名单前缀
private final String[] whiteListPrefix = {"/admin/login", "/admin/css", "/admin/js", "/admin/plugins", "/admin/editormd", "/admin/images"}; @Autowired
private RedisUtil redisUtil; /**
* 请求方法执行之前
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 在进入这个拦截器之前,对跨域提供支持
if (responseCors(response, request)) {
return false;
} // 获取用户访问的路由
String uri = request.getRequestURI(); LOGGER.info("UserAgent: {}", request.getHeader(USER_AGENT));
LOGGER.info("用户访问地址: {}, 来源地址: {}", uri, IPKit.getIpAddrByRequest(request)); // 获取登录用户同时刷新用户过期时间
UserInfoVO user = redisUtil.getLoginUser(request, true);
// 请求拦截
if (uri.startsWith("/admin") && user == null && verifyUriPrefix(uri)) {
this.responseResult(response);
return false;
} return true;
} /**
* 验证 uri 是否在白名单中
* @param uri 统一资源标志符/路由
* @return boolean
*/
private boolean verifyUriPrefix(String uri) {
if (uri == null) return false;
for (String prefix : whiteListPrefix) {
// 判断 uri 是否以白名单的前缀开头
if (uri.startsWith(prefix)) {
return false;
}
}
return true;
} /**
* 用户未登录 使用 response 返回结果
* @param response
* @throws IOException
*/
private void responseResult(HttpServletResponse response) throws IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
response.getWriter().println(JsonKit.toJSON(Result.fail(401, ErrorConstant.Auth.NOT_LOGIN)));
} /**
* 在进入这个拦截器之前, 对跨域提供支持
* @param response
* @param request
* @return
*/
private boolean responseCors(HttpServletResponse response, HttpServletRequest request) {
if (RequestMethod.OPTIONS.name().equals(request.getMethod())) {
response.setHeader("Cache-Control","no-cache");
response.setHeader("Access-control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");
response.setHeader("Access-Control-Allow-Headers", "*");
// 跨域时会首先发送一个OPTIONS请求,这里我们给OPTIONS请求直接返回正常状态
response.setStatus(HttpStatus.OK.value());
return true;
}
return false;
}
}

SpringBoot添加Cors跨域配置,解决No 'Access-Control-Allow-Origin' header is present on the requested resource的更多相关文章

  1. SpringBoot添加CORS跨域

    配置CORSConfiguration 添加CORS的配置信息,我们创建一个CORSConfiguration配置类重写如下方法,如图所示: @Override public void addCors ...

  2. (转)AJax跨域:No 'Access-Control-Allow-Origin' header is present on the requested resource

    在本地用ajax跨域访问请求时报错: No 'Access-Control-Allow-Origin' header is present on the requested resource. Ori ...

  3. 跨域原因及SpringBoot、Nginx跨域配置

    目录 概述 简单请求 跨域解决方案 概述 SpringBoot跨域配置 Nginx跨域配置 概述 MDN文档 Cross-Origin Resource Sharing (CORS) 跨域的英文是Cr ...

  4. As.net WebAPI CORS, 开启跨源访问,解决错误No 'Access-Control-Allow-Origin' header is present on the requested resource

    默认情况下ajax请求是有同源策略,限制了不同域请求的响应. 例子:http://localhost:23160/HtmlPage.html 请求不同源API http://localhost:228 ...

  5. 解决跨域No 'Access-Control-Allow-Origin' header is present on the requested resource.

    用angular发起http.get(),访问后端web API要数据,结果chrome报错:跨域了 Access to XMLHttpRequest at 'http://127.0.0.1:300 ...

  6. Webapi 跨域 解决解决错误No 'Access-Control-Allow-Origin' header is present on the requested resource 问题

    首先是web端(http://localhost:53784) 请求 api(http://localhost:81/api/)时出现错误信息: 查看控制台会发现错误:XMLHttpRequest c ...

  7. java、ajax 跨域请求解决方案('Access-Control-Allow-Origin' header is present on the requested resource. Origin '请求源' is therefore not allowed access.)

      1.情景展示 ajax调取java服务器请求报错 报错信息如下: 'Access-Control-Allow-Origin' header is present on the requested ...

  8. .Net Core 处理跨域问题Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource

    网页请求报错: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Or ...

  9. js跨域访问,No 'Access-Control-Allow-Origin' header is present on the requested resource

    js跨域访问提示错误:XMLHttpRequest cannot load http://...... No 'Access-Control-Allow-Origin' header is prese ...

随机推荐

  1. 《CNN Image Retrieval in PyTorch: Training and evaluati-ng CNNs for Image Retrieval in PyTorch》代码思路解读

    这是一个基于微调卷积神经网络的图像检索的代码实现,这里我就基于代码做一个实现思路的个人解读,如果有不对的地方或者不够详细的地方,欢迎大家指出. 代码的GitHub地址:filipradenovic/c ...

  2. Flink从Kafka取数WordCount后TableApi写入ES

    一.背景说明 需求为从Kafka消费对应主题数据,通过TableApi对数据进行WordCount后,基于DDL写法将数据写入ES. 二.代码部分 说明:代码中关于Kafka及ES的连接部分可以抽象到 ...

  3. Typora 配置码云图床

    目录 在码云创建一个项目作为自己床图 设置私人令牌 下载安装 PigGo Typora中设置图片上传选项 在码云创建一个项目作为自己床图 创建的项目必须为公开项目,创建的过程不细说了. 设置私人令牌 ...

  4. linux命令基础(一课)

    一.Linux命令基础 1.shell Linux系统中运行的一种特殊程序 在用户和内核之间充当'翻译官' 用户登录Linux系统时,自动加载一个shell程序 bash是Linux系统中默认使用的s ...

  5. JMeter定时器种类+详细教程举例

    首先,我们先了解一下定时器的常见种类以及它的作用. 原文地址:https://www.cnblogs.com/istart/p/11184533.html 一.定时器种类+作用 上面是我截图的自己有道 ...

  6. YOLO V4 :win10+cpu环境的体验

    1.前言 Yolo V3已经体验了,接下来是V4版本. 关于V4版本,学术界褒贬不一.从工业界实际应用角度看,V4做了不少的优化,精度提升了10%,速度提升了12%.详细参见: <如何评价新出的 ...

  7. Luat Demo | 一文读懂,如何使用Cat.1开发板实现Camera功能

    让万物互联更简单,合宙通信高效便捷的二次开发方式Luat,为广大客户提供了丰富实用的Luat Demo示例,便于项目开发灵活应用. 本期采用合宙全新推出的VSCode插件LuatIDE,为大家演示如何 ...

  8. canvas小画板——(3)笔锋效果

    画线准备 准备一个canvas <canvas id="canvasId" width="1000" height="800"> ...

  9. 【luogu P3807】【模板】卢卡斯定理/Lucas 定理(含 Lucas 定理证明)

    [模板]卢卡斯定理/Lucas 定理 题目链接:luogu P3807 题目大意 求 C(n,n+m)%p 的值. p 保证是质数. 思路 Lucas 定理内容 对于非负整数 \(n\),\(m\), ...

  10. 【PC桌面软件的末日,手机移动端App称王】写在windows11支持安卓,macOS支持ios,龙芯支持x86和arm指令翻译

    面对这场突如其来的变革,作为软件开发者,应该如何选择自己今后的发展方向?桌面软件开发领域还有前景吗? 起源 自从苹果发布m1处理器,让自家Mac支持IOS移动端app运行之后,彻底打破了移动端app和 ...