跨域是一种浏览器同源安全策略,即浏览器单方面限制脚本的跨域访问。
一、认识跨域
跨域(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配置源即可。
@BeanCorsConfigurationSource 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;}