前言

最近在做项目的时候,基于前后端分离的权限管理系统,后台使用 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资源会形成端口跨域。

解决跨域的常见方式

JSONP

由于浏览器允许一些带有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

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解决跨越方式

@CrossOrigin 注解

这种是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 方法。代码比较简单,也有注释

Filter过滤器方式

  1. 方式一
@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);
}
  1. 方式二

    基于servler 最原始的配置方式
@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启用CORS支持

如果项目中使用了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);
}

SpringBoot 优雅配置跨域多种方式及Spring Security跨域访问配置的坑的更多相关文章

  1. spring boot rest 接口集成 spring security(1) - 最简配置

    Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...

  2. Spring Security 之Session管理配置

    废话不多说,直接上代码.示例如下: 1.   新建Maven项目  session 2.   pom.xml <project xmlns="http://maven.apache.o ...

  3. Spring事务配置的五种方式和spring里面事务的传播属性和事务隔离级别

    转: http://blog.csdn.net/it_man/article/details/5074371 Spring事务配置的五种方式 前段时间对Spring的事务配置做了比较深入的研究,在此之 ...

  4. SpringBoot学习笔记(2):引入Spring Security

    SpringBoot学习笔记(2):用Spring Security来保护你的应用 快速开始 本指南将引导您完成使用受Spring Security保护的资源创建简单Web应用程序的过程. 参考资料: ...

  5. Spring Security 入门(1-3-2)Spring Security - http元素 - intercept-url配置

    http元素下可以配置登录页面,也可以配置 url 拦截. 1.直接配置拦截url和对应的访问权限 <security:http use-expressions="false" ...

  6. spring security+cas(cas proxy配置)

    什么时候会用到代理proxy模式? 举一个例子:有两个应用App1和App2,它们都是受Cas服务器保护的,即请求它们时都需要通过Cas 服务器的认证.现在需要在App1中通过Http请求访问App2 ...

  7. Spring Security OAuth2之resource_id配置与验证

    一.resource_id的作用 Spring Security OAuth2 架构上分为Authorization Server认证服务器和Resource Server资源服务器.我们可以为每一个 ...

  8. Springboot通过cors解决跨域问题(解决spring security oath2的/oauth/token跨域问题)

    @Bean public CorsFilter corsFilter() { final UrlBasedCorsConfigurationSource source = new UrlBasedCo ...

  9. spring security 跨域防伪攻击

    applicationContext-security.xml中配置 <http use-expressions="true" disable-url-rewriting=& ...

随机推荐

  1. 基于Grunt&Mocha 搭建Nodejs自动化单元测试框架(含代码覆盖率统计)

    Introduction Grunt 是一个基于任务的JavaScript 世界的构建工具 Mocha 是具有丰富特性的 JavaScript 测试框架,可以运行在 Node.js 和浏览器中,使得异 ...

  2. 两个list<object> 比较 得到相同数据 差异数据

    package com.lizi.admin.utils.contrast;import java.lang.reflect.InvocationTargetException;import java ...

  3. 将数据导入PostGIS

    #!/usr/bin/env python # -*- coding: utf-8 -*- import subprocess # database options db_schema = " ...

  4. C#.Net 上传图片,限制图片大小,检查类型完整版

    C#.Net 上传图片,限制图片大小,检查类型完整版 源代码: 处理图片类,如检查图片大小,按宽度比例缩小图片 public class CImageLibrary{   public enum Va ...

  5. 常用的SQL数据库语句总结

    1as 的用处 as可以对表和列取别名 在开发过程中经常遇到开始给某一个的字段去field1的名称,但后来有感觉field1字段指定不确切,于是又把此字段改成了field2,由于开始认 为field1 ...

  6. 记PHP面向对象编程

    访问控制 public(公开的):可以在类中.子类中.类外访问. protected(受保护的):只能在类本身及子类中访问. private(私有的):只能在声明他们的类中进行访问,私有的类成员不能被 ...

  7. Spring框架——AOP代理

    我们知道AOP代理指的就是设计模式中的代理模式.一种是静态代理,高效,但是代码量偏大:另一种就是动态代理,动态代理又分为SDK下的动态代理,还有CGLIB的动态代理.Spring AOP说是实现了AO ...

  8. 解决ajax 跨域请求问题

    浏览器console报错: has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is 解决: 服务端加入代 ...

  9. href和src区别

    href常见于link a 元素, 是Hypertext Reference的缩写,表示超文本引用.用来建立当前元素和文档之间的链接. href引用css文件时,浏览器会识别该文档为css文档,就会并 ...

  10. Dropbox 在 Ubuntu 上需要认证授权的问题

    在 Ubuntu 上,通过 Ubuntu软件中心 搜索下载安装了 Dropbox . 运行时,弹出如下图的提示. 输入密码,点击 授权 后,没有出现 Dropbox 的运行界面. 再次点击运行,仍会出 ...