- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
最近在做项目的时候,基于前后端分离的权限管理系统,后台使用 Spring Security 作为权限控制管理, 然后在前端接口访问时候涉及到跨域,但我怎么配置跨域也没有生效,这里有一个坑,在使用Spring Security
时候单独配置,SpringBoot 跨越还不行,还需要配置Security 跨域才行。
跨域是一种浏览器同源安全策略,即浏览器单方面限制脚本的跨域访问
在 HTML 中,<a>, <form>, <img>, <script>, <iframe>, <link>
等标签以及 Ajax 都可以指向一个资源地址,而所谓的跨域请求就是指:当前发起请求的域与该请求指向的资源所在的域不一样。这里的域指的是这样的一个概念:我们认为若协议 + 域名 + 端口号均相同,那么就是同域
当前页面URL和请求的URL首部(端口之前部分)不同则会造成跨域。通俗点讲就是两个URL地址,端口之前部分,只要有一点不同即发生跨域。
例如:
1. 在http://a.baidu.com下访问https://a.baidu.com资源会形成协议跨域。
2. 在a.baidu.com下访问b.baidu.com资源会形成主机跨域。
3. 在a.baidu.com:80下访问a.baidu.com:8080资源会形成端口跨域。
由于浏览器允许一些带有src属性的标签跨域,常见的有iframe、script、img
等,所以JSONP
利用script
标签可以实习跨域
前端通过script标签请求,并在callback中指定返回的包装实体名称为jsonp(可以自定义)
<script src="http://aaa.com/getusers?callback=jsonp"></script>
后端将返回结果包装成所需数据格式
jsonp({
"error":200,
"message":"请求成功",
"data":[{
"username":"张三",
"age":20
}]
})
总结:JSONP实现起来很简单,但是只支持GET请求跨域,存在较大的局限性
CORS是一个W3C标准,全称是”跨域资源共享”(Cross-origin resource sharing),允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
规范中有一组新增的HTTP首部字段 它通过服务器增加一个特殊的Header[Access-Control-Allow-Origin]来告诉客户端跨域的限制,如果浏览器支持CORS、并且判断Origin通过的话,就会允许XMLHttpRequest发起跨域请求
注意:CORS不支持IE8以下版本的浏览器
CORS Header属性 | 解释 |
---|---|
Access-Control-Allow-Origin | 允许http://www.xxx.com域(自行设置,这里只做示例)发起跨域请求 |
Access-Control-Max-Age | 设置在86400秒不需要再发送预校验请求 |
Access-Control-Allow-Methods | 设置允许跨域请求的方法 |
Access-Control-Allow-Headers | 允许跨域请求包含content-type |
Access-Control-Allow-Credentials | 设置允许Cookie |
这种是SpringBoot自带的注解,使用非常简单,只需要在对应的接口添加上次注解就行
就表示这个接口支持跨域,其中origins = "*"
表示所有的地址都可以访问这个接口,也可以写具体的地址,表示只有这个地址访问才能访问到接口
可以注解在类上,和方法上,类上表示此controller
所有接口都支持跨域,单个方法上表示只有这个接口支持跨域
这种方法虽然优雅简单,但是缺点也不小,需要跨域的接口都需要加上这个注解,这对前后端分离的项目是不友好的,需要添加很多次,所以这种方式基本上用的很少
重写WebMvcConfigurer的addCorsMappings
方法
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")//项目中的所有接口都支持跨域
.allowedOriginPatterns("*")//所有地址都可以访问,也可以配置具体地址
.allowCredentials(true)
.allowedMethods("*")//"GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS"
.maxAge(3600);// 跨域允许时间
}
}
注意allowedOrigins("*")
和allowCredentials(true)
为true
时候会出现错误需要改成allowedOriginPatterns("*")
或者单独指定接口allowedOrigins("http//www.baidu.com")
@Configuration
表示是配置类,在项目启动的时候会加载。实现WebMvcConfigurer
接口并重写addCorsMappings
方法。代码比较简单,也有注释
@Bean
public CorsFilter corsFilter() {
//1.添加CORS配置信息
CorsConfiguration config = new CorsConfiguration();
//放行哪些原始域
config.addAllowedOrigin("*");
//是否发送Cookie信息
config.setAllowCredentials(true);
//放行哪些原始域(请求方式)
config.addAllowedMethod("*");
//放行哪些原始域(头部信息)
config.addAllowedHeader("*");
//暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
config.addExposedHeader("*");
//2.添加映射路径
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
//3.返回新的CorsFilter.
return new CorsFilter(configSource);
}
@Slf4j
@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, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, client_id, uuid, Authorization");
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setHeader("Pragma", "no-cache");
filterChain.doFilter(servletRequest,response);
}
}
以上三种方法都可以解决问题,最常用的应该是第一种、第二种,控制在自家几个域名范围下足以,一般没必要搞得太细。
这三种配置方式都用了的话,谁生效呢,类似css中样式,就近原则
,懂了吧
如果项目中使用了Spring Security
配置了上面跨越方式还不行,需要单独指定Spring Security
跨域
否则跨越不会生效
Spring Security对CORS提供了非常好的支持,只需在配置器中启用CORS支持,并编写一 个CORS配置源即可
@Override
protected void configure(HttpSecurity http) throws Exception {
// We don't need CSRF for this example
http.cors().and().csrf().disable()
// dont authenticate this particular request
.authorizeRequests().antMatchers("/", "/*.html", "/favicon.ico", "/css/**", "/js/**", "/fonts/**", "/layui/**", "/img/**",
"/v3/api-docs/**", "/swagger-resources/**", "/webjars/**", "/pages/**", "/druid/**",
"/statics/**", "/login", "/register").permitAll().
// all other requests need to be authenticated
anyRequest().authenticated().and().
// make sure we use stateless session; session won't be used to
// store user's state.
//覆盖默认登录
exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()
// 基于token,所以不需要session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// Add a filter to validate the tokens with every request
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOriginPattern("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
corsConfiguration.setAllowCredentials(true);
source.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(source);
}
前言 每日站会(Daily Standup)是团队统一节奏的、在固定时间发生的、帮助团队内部快速同步进展的敏捷实践活动: 站会的目的是让团队能更好地对齐 Sprint 目标;
jdbcTemplate 中的queryForList,你真的懂吗? 你想象中的queryForList是不是应该长成下面这种模样? String sql = "select *
python是一门清晰简洁的语言,如果你对一些细节不了解的话,就会掉入到那些深不见底的“坑”里,下面,我就来总结一些python里常见的坑。 列表创建和引用 嵌套列表的创建 使用*号来创建一个
如今,在DevOps当中建立安全体系显得比以往任何时候都更加重要。《2021年企业DevOps技能提升报告》指出,56%的受访者表示DevSecOps已经成为自动化工具中的一大必备要素。然而,D
前言 相信看到这个题目,可能大家都觉得是一个老生常谈的月经topic了。一直以来其实把握一个“值传递”基本上就能理解各种情况了,不过最近遇到了更深一点的“小坑”,与大家分享一下。 首先还是从最简
前言 Go 中的for range组合可以和方便的实现对一个数组或切片进行遍历,但是在某些情况下使用for range时很可能就会被"坑",下面用一段代码来模拟下:
大家好,我是明哥。 在开始之前,先考你一个非常 Go 味的经典问题:如何判断一个 interface{} 的值是否为 nil ? 这也是面试有可能会被问到的一个问题,这个问题很 “迷”,平时
ava并发包有很大一部分内容都是关于并发容器的,因此学习和搞懂这部分的内容很有必要。 Java 1.5 之前提供的同步容器虽然也能保证线程安全,但是性能很差,而 Java 1.5 版本之后提供的并发
大家好,我是煎鱼。 前几天在读者交流群里看到一位小伙伴,针对 interface 的使用有了比较大的疑惑。 无独有偶,我也在网上看到有小伙伴在 Go 面试的时候被问到了:
我是一名优秀的程序员,十分优秀!