SpringBoot添加Cors跨域配置,解决No 'Access-Control-Allow-Origin' header is present on the requested resource
什么是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的更多相关文章
- SpringBoot添加CORS跨域
配置CORSConfiguration 添加CORS的配置信息,我们创建一个CORSConfiguration配置类重写如下方法,如图所示: @Override public void addCors ...
- (转)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 ...
- 跨域原因及SpringBoot、Nginx跨域配置
目录 概述 简单请求 跨域解决方案 概述 SpringBoot跨域配置 Nginx跨域配置 概述 MDN文档 Cross-Origin Resource Sharing (CORS) 跨域的英文是Cr ...
- 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 ...
- 解决跨域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 ...
- Webapi 跨域 解决解决错误No 'Access-Control-Allow-Origin' header is present on the requested resource 问题
首先是web端(http://localhost:53784) 请求 api(http://localhost:81/api/)时出现错误信息: 查看控制台会发现错误:XMLHttpRequest c ...
- 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 ...
- .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 ...
- 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 ...
随机推荐
- 06:JS(02)
对象 一切皆对象 数组(类似于python里面的列表) [] var l = [11,22,33,44,55] typeof l "object" var l1 = [11,'sd ...
- 白日梦的MySQL专题(第38篇文章)8分钟回顾MySQL的索引
目录 公众号首发-推荐阅读原文-格式更好看 一.导读 二.聚簇索引 三.二级索引 四.联合索引 4.1.什么是联合索引 4.2.左前缀原则 4.3.联合索引的分组&排序 五.覆盖索引 六.倒排 ...
- 「10.14」小P的2048(模拟)·小P的单调数列(性质,DP)·小P的生成树(乱搞)
A. 小P的2048 模拟.....又没啥可说的,以后要认真打打模拟题了... B. 小P的单调数列 考场$n^2log(n)$的SB思路有人听吗 正解当然不是这样, 事实上我们每次选取的只有一段区间 ...
- 【模拟8.10】Weed(线段树)
考试只好随便骗骗分过去啦啦啦..... 正解是玄学线段树: 以每个操作为叶子节点,我们定义几个变量ce表示层数,h表示高度,add表示所减的层数 那么问题转化为单点修改的问题输出直接是根节点答案 但是 ...
- Netty 框架学习 —— 基于 Netty 的 HTTP/HTTPS 应用程序
通过 SSL/TLS 保护应用程序 SSL 和 TLS 安全协议层叠在其他协议之上,用以实现数据安全.为了支持 SSL/TLS,Java 提供了 javax.net.ssl 包,它的 SSLConte ...
- token & refresh token 机制总结
token & refresh token 机制总结 废话 我在项目上写了个配置页面,之前很简单直接登录,毕竟配置页面自己人用就没有做token机制,后来公司的安全审核不过,现在要加上toke ...
- lms框架服务注册中心
服务注册中心原理 在分布式系统里的注册中心.原理是将部署服务的机器地址记录到注册中心,服务消费者在有需求的时候,只需要查询注册中心,输入提供的服务名,就可以得到地址,从而发起调用. 在微服务架构下,主 ...
- POJ 2236 Wireless Network 第一次做并查集,第一次写博客
题意是判断两台电脑是否能通讯,两台修好的电脑距离在指定距离内可直接通讯,且两台修好的电脑能通过一台修好的电脑间接通讯.代码如下: #include <iostream> #include ...
- Place the Robots 需要较强的建图能力
Place the Robots 思路:在任意一个点格子放机器人,那么它所在的行和列被控制了.我们对每一行或每一列连续的空地(草地忽视)称之为块,给每一行和每一列的块标号, 每一行的快与每一列的快相交 ...
- 『心善渊』Selenium3.0基础 — 21、Selenium实现绕过验证码进行登陆
目录 1.验证码问题 2.处理验证码的方法 3.Selenium绕过验证码登陆的实现 4.总结 5.补充练习 1.验证码问题 对于Web应用来说,大部分的系统在用户登录时,都要求用户输入验证码.验证码 ...