Spring MVC 实现跨域请求方案

  JavaWeb项目如果采用前后端完全分离架构,前端和后端部署在不同的服务器上,前端负责页面呈现和数据展示,后端提供数据接口给前端调用,这就产生了跨域请求。

  跨域请求:指的是前端(一般指浏览器)向其它应用服务发起访问请求。一般发生在主域名不同、或子域名不同、或端口不同或协议不同的两个应用服务器之间的调用。一般指的是使用ajax来调用。

  实现跨域请求有解决方案,本篇只对SpringMVC自带支持CORS技术进行详细描述,CORS支持多种请求方式(get,post...),在前端处理和普通请求几乎一样,后端配置也容易。

CORS协议

  浏览器基于同域安全策略(the same-origin security policy)会禁止跨域请求,即JavaScriptCookie只能访问同域下的内容。
  W3C制定了CORS标准,全称Cross-Origin Resource Sharing(跨域资源共享),是一种跨域访问验证机制,允许浏览器向跨域服务器发送请求的技术,解决了Ajax只能同域请求的问题。

  目前所有的浏览器都支持CORS技术,该技术执行是浏览器自动完成的,不需要用户参与。当浏览器发现Ajax跨域请求会自动添加一些头信息,有时还会多一次附加请求,服务器端需要实现CORS接口。

CORS常见Header

Header信息 描述
Access-Control-Allow-Origin 指定授权访问域。多个域名可以用逗号隔开。如www.aaa.com,www.bbb.com。`*`表示不限制域名,允许所有跨域请求(不建议使用)
Access-Control-Allow-Methods 授权请求的方法(GET,POST,PUT,DELETE等),*表示所有方式
Access-Control-Allow-Credentials 是否允许请求带有验证信息(即Cookie信息)。CORS请求默认会带上Cookie(相当于省略了:withCredentials = true), 设为false,则显式指带请求不带Cookie
Access-Control-Allow-Headers 允许自定义的头部,逗号隔开。如:Content-Type, x-requested-with, Authorization等
Access-Control-Max-Age 在CROS协议中,一个AJAX请求被分成了两步。第一步OPTION预检测请求,第二步为正式请求。该项是设置预检测请求的有效期,单位,在有效期内,不再发送预检测请求
Access-Control-Expose-Headers 允许客户端可以访问到其他的首部信息

W3C-CORS官方说明文档

SpringMVC方案

  SpringMVC4.2 版本开始增加了CORS协议的支持,提供了两种非常容易使用配置:@CrossOrigin注解或在配置文件里设置mvc:cors

使用@CrossOrigin注解

  @CrossOrigin注解可以放在类上,作用域是该类下的所有方法;也可以放在方法上,只对该方法授权跨域请求。
  若使用@CrossOrigin注解,则该注解的methods属性与@RequestMappingmethod属性必须有一个显式设置请求方式(post,get),若这两个注解都没有设置请求方式,则跨域请求会报不允许的错误;若两个都显式设置了请求方式,则@RequestMappingmethod优先级高于@CrossOriginmethods

@CrossOrigin注解参数说明:

  1. origins:String[]类型,指的是允许跨域请求的源域名,未定义或*表示允许所有跨域请求(不建议使用)。
  2. methods: RequestMethod[]类型,指的是允许跨域请求的方式(get、post),未定义则由@RequestMapping注解的method决定。
  3. maxAge: long类型,指的是预检测请求的有效时间,单位,在有效时间内的请求不再发送预检测请求,未定义则默认为1800秒(30分钟),设置合理的时间值,可以减少预检则请求的次数,提高请求响应的速度。
  4. allowedHeaders:String[]类型,指的是请求可以使用的头信息,未定义或*表示允许所有的头信息。
  5. allowCredentials:String类型,但是boolean值,指的是浏览器请求是否要包含cookie信息,true表示需要包含cookie信息,false表示不需要包含cookie信息,未定义表示默认要求包含。
  6. exposedHeaders:String[]类型,指的是客户端可以获取该响应头处理一些信息,未定义则表示空。

@CrossOrigin注解使用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Controller
@CrossOrigin(origins = {"http://localhost:9000", "http://127.0.0.1"},
maxAge = 36000,
methods = {RequestMethod.POST, RequestMethod.GET},
allowCredentials = "true",
allowedHeaders = {"header1", "authorization"},
exposedHeaders = {"header1", "header2"})
@RequestMapping(value = "/api", method = {RequestMethod.POST})
public class ApiController {

@RequestMapping(value = "/apiUserData")
@ResponseBody
public User userData() {
User user = new User()
.setUserName("root")
.setPassword("root123")
.setAge(26);
return user;
}
}

配置SpringMVC.xml

也可以在springmvc.xml文件配置,根据配置的参数决定作用域。

参数说明:

  1. path:允许跨域访问的Controller层映射路径。*表示下一级,**表示下一级所有。【必须】
  2. allowed-origins:允许跨域请求的源路径(域名),可设置多个,*和默认表示允许所有源的跨域请求。
  3. allowed-methods:允许跨域访问的请求方式,可设置多个,*表示允许所有请求方式,默认是GET,POST两种。
    该参数的设置(POST,GET)必须大写,必须与@RequestMapping注解的method的值一致,否则报不允许访问错误。
  4. allowed-headers:头信息,*和默认是允许所有的头信息。
  5. allow-credentials:请求是否要求带Cookies,String类型的boolean值,默认是true
  6. exposed-headers:默认是空,前端可以获取该头信息用于处理业务。
  7. max-age:预检测请求的有效时间,单位,在时间范围内不发送预检测请求,默认1800秒(30分钟)。

以上参数的默认指的是在文件中不设置,没有属性名和值。
path必须配置,其它参数如果不配置则默认允许所有源路径的跨域请求,允许GET,POST方法,允放所有的消息头,默认要求请求带上Cookiemax-age默认30分钟。

springmvc.xml配置示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<mvc:cors>
<mvc:mapping path="/**" allowed-methods="*" />
<mvc:mapping path="/api/**"
allowed-origins="http://localhost, http://localhost:9000"
allowed-methods="POST"
allowed-headers="header1, header2, header3"
allow-credentials="true"
exposed-headers="CORS, header1, header2"
max-age="36000"/>

<mvc:mapping path="/resources/**"
allowed-origins=""
allowed-methods=""
allowed-headers=""/>
</mvc:cors>

配置参数及默认值参考spring-mvc.xsd
Web跨域分析与解决

作者

光星

发布于

2018-02-03

更新于

2022-06-17

许可协议

评论