1.什么是跨域?
当一个页面请求url的协议、域名、端口三者之间任何一者与当前页面url不同即为跨域。举个例子:
2.为什么会出现跨域问题
出现跨域问题是源于浏览器的同源策略限制的。同源策略(Same origin policy)是一种约定,它是浏览器针对安全功能的一种实现,如果缺少了同源策略,浏览器很容易受到XSS,CSFR等网络攻击。
3.跨域会导致什么问题
- 不能读取非同源网页中的 Cookie、LocalStorage 等数据
- 不能接触非同源网页的 DOM 结构
- 不能向非同源地址发送 AJAX 请求
跨域的现象:
4.跨域问题的解决方案
4.1 CORS
CORS 跨域资源分享(Cross-Origin Resource Sharing)的办法是让每一个页面需要返回一个名为Access-Control-Allow-Origin的http头来允许非同源的站点访问 一般请求只需在服务器端设置Access-Control-Allow-Origin,如果是带cookie的跨域请求那么前后端都要进行设置
【前端】 ①原生ajax
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.open('post', 'http://water.com/v1', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('user=gwx');
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
};
② jQuery ajax
$.ajax({
url: 'http://water.com/v1',
type: 'get'
data: {}
xhrFields:
withCredentials: true
}
})
③vue-resource
Vue.http.options.credentials = true
④ axios
axios.defaults.withCredentials = true
【后端SpringBoot】 在服务器响应客户端的时候,带上Access-Control-Allow-Origin ① 使用 @CrossOrigin 注解
@RequestMapping("/v1")
@RestController
@CrossOrigin("https://water.com")
public class CorsTestController {
@GetMapping("/test")
public String sayHello() {
return "success";
}
}
② CORS全局配置
@Configuration
public class CorsConfig {
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig());
return new CorsFilter(source);
}
}
③ 拦截器实现
@Component
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.addHeader("Access-Control-Allow-Credentials", "true");
res.addHeader("Access-Control-Allow-Origin", "*");
res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
res.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN");
if (((HttpServletRequest) request).getMethod().equals("OPTIONS")) {
response.getWriter().println("ok");
return;
}
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}
4.2 nginx反向代理
通过修改 nginx.conf 配置文件做代理转发
server {
listen 80;
server_name www.yamky.com;
location ^~/gwx/ {
proxy_pass http://xxx.com:80;//你要转发的地址
proxy_set_header Host $host:$server_port;
proxy_set_header Remote_Addr $remote_addr;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 2048m;
}
4.3 使用网关解决
|