跨域资源共享(CORS):通过修改Http协议header的方式,实现跨域。说的简单点就是,通过设置HTTP的响应头信息,告知浏览器哪些情况在不符合同源策略的条件下也可以跨域访问,浏览器通过解析Http协议中的Header执行具体判断。具体的Header如下:
CORS跨域常用header
Access-Control-Allow-Origin: 允许哪些ip或域名可以跨域访问
Access-Control-Max-Age: 表示在多少秒之内不需要重复校验该请求的跨域访问权限
Access-Control-Allow-Methods: 表示允许跨域请求的HTTP方法,如:GET,POST,PUT,DELETE
Access-Control-Allow-Headers: 表示访问请求中允许携带哪些Header信息,如:Accept、Accept-Language、Content-Language、Content-Type
目录
1.使用CorsFilter进行全局跨域配置
2. 重写WebMvcConfigurer的addCorsMappings方法(全局跨域配置)
3.使用CrossOrigin注解(局部跨域配置)
4 使用HttpServletResponse设置响应头(局部跨域配置)
创建一个配置类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/**
* @author xiaomifeng1010
* @version 1.0
* @date: 2022/4/6 11:37
* @Description 全局跨域处理
*/
@Configuration
public class GlobalCorsConfigure {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
//开放哪些ip、端口、域名的访问权限,星号表示开放所有域
config.addAllowedOrigin("*");
//是否允许发送Cookie信息
config.setAllowCredentials(true);
//开放哪些Http方法,允许跨域访问
config.addAllowedMethod(HttpMethod.GET);
config.addAllowedMethod(HttpMethod.POST);
config.addAllowedMethod(HttpMethod.PUT);
config.addAllowedMethod(HttpMethod.DELETE);
//允许HTTP请求中的携带哪些Header信息
config.addAllowedHeader("*");
//暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
config.addExposedHeader("*");
//添加映射路径,“/**”表示对所有的路径实行全局跨域访问权限的设置
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
return new CorsFilter(configSource);
}
}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author xiaomifeng1010
* @version 1.0
* @date: 2022/4/6 11:37
* @Description 全局跨域处理
*/
@Configuration
public class GlobalCorsConfigure {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") //添加映射路径,“/**”表示对所有的路径实行全局跨域访问权限的设置
.allowedOrigins("*") //开放哪些ip、端口、域名的访问权限
.allowCredentials(true) //是否允许发送Cookie信息
.allowedMethods("GET","POST", "PUT", "DELETE") //开放哪些Http方法,允许跨域访问
.allowedHeaders("*") //允许HTTP请求中的携带哪些Header信息
.exposedHeaders("*"); //暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
}
};
}
}
@RequestMapping("/cors")
@ResponseBody
@CrossOrigin(origins = "http://localhost:8080", maxAge = 3600)
public String cors( ){
return "cors";
}
这种方式略显麻烦,不建议在SpringBoot项目中使用。
@RequestMapping("/cors")
@ResponseBody
public String cors(HttpServletResponse response){
//使用HttpServletResponse定义HTTP请求头,最原始的方法也是最通用的方法
response.addHeader("Access-Control-Allow-Origin", "http://localhost:8080");
return "cors";
}
注意事项,如果你的项目中使用了某个独立的认证框架,那么springboot中提供的跨域配置可能会不生效,例如使用sa-token这个授权认证的框架后,解决跨域问题的话,亲测直接使用上边前三种方法是不生效的,因此,需要使用sa-token中提供的过滤器进行配置
如下:
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.jwt.StpLogicJwtForStyle;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author xiaomifeng1010
* @version 1.0
* @date: 2022/4/1 10:51
* @Description
*/
@Configuration
@Slf4j
public class SaTokenConfigure {
/**
* @description: Sa-Token 整合jwt(Style模式)
* @author: xiaomifeng1010
* @date: 2022/4/1
* @param
* @return: StpLogic
**/
@Bean
public StpLogic getStpLogicJwt() {
return new StpLogicJwtForStyle();
}
/**
* @description: 注册 Sa-Token全局过滤器
* @author: xiaomifeng1010
* @date: 2022/4/1
* @param
* @return: SaServletFilter
**/
@Bean
public SaServletFilter getSaServletFilter() {
return new SaServletFilter()
// 指定 拦截路由 与 放行路由
.addInclude("/**").addExclude("/favicon.ico")
// 认证函数: 每次请求执行
.setAuth(obj -> {
log.info("---------- 进入Sa-Token全局认证 -----------");
// 登录认证 -- 拦截所有路由,并排除/user/doLogin和获取验证码的接口 用于开放登录
SaRouter.match("/h5/**").notMatch("/h5/getCaptcha","/h5/login").check(() -> StpUtil.checkLogin());
})
// 异常处理函数:每次认证函数发生异常时执行此函数
.setError(e -> {
log.error("---------- 进入Sa-Token异常处理 -----------");
log.error(e.getMessage());
return SaResult.error(e.getMessage());
})
// 前置函数:在每次认证函数之前执行
.setBeforeAuth(r -> {
// 设置一些安全响应头
SaHolder.getResponse()
// 服务器名称
.setServer("sa-server")
// 允许指定域访问跨域资源
.setHeader("Access-Control-Allow-Origin", "*")
// 允许所有请求方式
.setHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS,DELETE")
// 有效时间
.setHeader("Access-Control-Max-Age", "3600")
// 允许的header参数
.setHeader("Access-Control-Allow-Headers", "*")
// 是否可以在iframe显示视图: DENY=不可以 | SAMEORIGIN=同域下可以 | ALLOW-FROM uri=指定域名下可以
// .setHeader("X-Frame-Options", "SAMEORIGIN")
// 是否启用浏览器默认XSS防护: 0=禁用 | 1=启用 | 1; mode=block 启用, 并在检查到XSS攻击时,停止渲染页面
.setHeader("X-XSS-Protection", "1; mode=block")
// 禁用浏览器内容嗅探
.setHeader("X-Content-Type-Options", "nosniff")
;
})
;
}
}
在这个配置类中也有一个注意事项:就是异常处理时,不要使用你在项目中自定义的 统一响应封装对象,需要使用sa-token中自带的统一响应封装对象SaResult,不然返回的对象格式不是标准的json格式,亲自试过踩坑