跨域是一种浏览器同源安全策略,即浏览器单方面限制脚本的跨域访问。
一、认识跨域
跨域(Cross-Origin)指的是在Web开发中,当一个网页的内容要从不同源(即不同的域名、协议或端口)获取时,就会发生跨域问题。浏览器会根据“同源策略”(Same-Origin Policy)的限制阻止网页从其他域名下的资源(如JavaScript、CSS、图片等)获取数据或调用其他网站的API接口。
同源策略是浏览器实现的一种安全策略,它限制了一个网页的脚本只能访问同源下的资源,而不能跨域访问其他域名下的资源,这样可以防止恶意的脚本窃取用户的敏感信息。跨域问题是Web开发中比较常见的问题,需要特别处理才能解决。
二、实现跨域之JSONP
SONP(JSON with Padding)是一种跨域请求的解决方案,它利用了script标签没有跨域限制的特性来实现。JSONP的原理是利用了script标签可以跨域加载资源的特性,通过动态创建一个script标签,将需要获取数据的URL作为其src属性,再在URL中加入一个回调函数的名称,服务器在返回数据时,将数据包装在该回调函数中,前端页面通过该回调函数获取数据。
以下是JSONP的一个示例:
后端代码:
在这个例子中,后端会返回一个JSON对象,对象的内容是一个名为John的人的姓名和年龄30。
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class JsonpServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("application/javascript;charset=utf-8");
PrintWriter out = response.getWriter();
String callback = request.getParameter("callback");
String jsonpStr = callback + "({\"name\":\"John\",\"age\":30})";
out.print(jsonpStr);
out.flush();
out.close();
}
}
前端代码:
在这个例子中,当用户点击“获取数据”按钮时,会动态创建一个script标签,并设置其src属性为http://localhost:8080/jsonp?callback=callback,其中callback是前端定义的回调函数名。浏览器会自动加载该URL,从而触发服务器的请求。服务器在返回数据时,将数据包装在callback函数中,最终在前端页面中调用callback函数,从而获取数据并输出到控制台。
<!DOCTYPE html>
<html>
<head>
<title>JSONP示例</title>
<script>
function callback(data) {
console.log(data);
}
</script>
</head>
<body>
<button onclick="getData()">获取数据</button>
<script>
function getData() {
var script = document.createElement('script');
script.src = 'http://localhost:8080/jsonp?callback=callback';
document.head.appendChild(script);
}
</script>
</body>
</html>
三、实现跨域之CORS
CORS(Cross-Origin Resource Sharing,跨域资源共享)是一种机制,用于在跨域访问时,允许网页的某些请求能够获得来自其他域的服务器资源。在同源策略(Same-Origin Policy)限制下,浏览器只允许当前网页与同一域名下的服务器进行交互,而CORS则是一种解决跨域问题的方案。
当浏览器发起跨域请求时,例如在网页中向其他域名的服务器发起请求,会被浏览器拦截,并发送一个预检请求(preflight request)给服务器。服务器在收到预检请求后,可以在响应头中设置Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers等字段,来告知浏览器哪些请求是被允许的。如果服务器返回的响应头中包含了与请求所设置的Origin、Method、Headers等相匹配的字段,那么浏览器就会允许该请求发送,并将响应内容返回给网页。
CORS的实现需要客户端和服务端的双重支持,一般需要服务端进行相关的配置,以便允许客户端跨域访问。
四、启用Spring Security的CORS支持
spring security对CORS提供了非常好的支持,只需在配置器中启用CORS支持,并编写一个CORS配置源即可。
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
//允许从百度站点跨域
configuration.setAllowedOrigins(Arrays.asList("https://www.baidu.com"));
//允许使用GET和POST方法
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
//允许带凭证
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
//对所有URL生效
source.registerCorsConfiguration("/**",configuration);
return source;
}