跨域及跨域请求伪造详解

什么是跨域?

简单来说,就是我在一个站点向另一个站点发送了请求(ajax或者链接),只要这两个站点HTTP协议、域名或是端口中有一个不一样,说明发送了跨域。

由于浏览器的同域安全策略(the same-origin security policy),这种跨域请求会被禁止。

eg.如下为在一个站点向另一个站点发送请求。
在这里插入图片描述

跨域问题解决

(1)@CrossOrigin:该注解有一个origins参数,可配置允许进行跨域的站点。

@CrossOrigin(origins = {"http://b.com:8080"})

(2)在请求接口中加入如下代码,表示允许某个站点的跨域请求,将http://b.com:8080改为 * 表示关闭跨域,也可以配置一个拦截器在拦截器中进行配置。

response.setHeader(“Access-Control-Allow-Origin”, “http://b.com:8080”);

(3)使用spring提供的拦截器。

@Configuration
public class CorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*"); // 允许进行跨域请求的站点
        urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration); // 拦截的路径
        return new CorsFilter(urlBasedCorsConfigurationSource);
    }
}

(4)多个站点的请求都映射到一个站点,再使用nginx进行转发,将这一个站点的请求转发到多个站点。

	server {
        listen       8080;
        server_name  c.com;
        location /a {
            proxy_pass  http://a.com:8080;
        }
        location /b {
            proxy_pass  http://b.com:8080;
        }
    }

跨域请求伪造

跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF,是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。

由于cookie是跟着站点的,请求时请求会带着该站点下的cookie,因此也衍生出针对cookie的csrf(Cross-site request forgery)攻击,也就是跨站请求伪造。

针对cookie的csrf示例

跨域及跨域请求伪造详解_第1张图片

(1)在hosts文件将127.0.0.1映射两个域名。

127.0.0.1       a.com
127.0.0.1       b.com

(2)创建两个请求api,一个用于用户登录a.com,一个用于用户调用b.com后向a.com发送请求。

@RestController
public class SessionController {
    private Vector loginUsers = new Vector<String>();
    @GetMapping("/login")
    public String login(HttpServletResponse response) {
        String token = UUID.randomUUID().toString();
        Cookie cookie = new Cookie("token", token);
        loginUsers.add(token);
        response.addCookie(cookie);
        return "登录成功";
    }
    @GetMapping("/deleteSomething")
    public String deleteSomething(HttpServletRequest request) {
        for (Cookie cookie : request.getCookies()) {
            if ("token".equals(cookie.getName()) && loginUsers.indexOf(cookie.getValue()) >= 0) {
                return "删掉什么东西";
            }
        }
        return "无权限";
    }
}

(3)用户访问b.com的页面


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>另一个页面title>
head>
<body>
    <a href="http://a.com:8080/deleteSomething">在b.com域名下发送一条请求到a.coma>
body>
html>

(4)准备就绪,通过a.com:8080/login进行登录

跨域及跨域请求伪造详解_第2张图片

(5)访问b.com:8080/index.html

在这里插入图片描述
(6)点击在b.com下发送一条请求到a.com

跨域及跨域请求伪造详解_第3张图片

可以看到,csrf攻击生效了。

解决方案:

  • 请求时将token放到header中,后端校验时再从header中拿出来,这样请求时由于header中没有token,csrf也就失效了(或者将token作为请求的参数,效果一样)。
  • 校验请求header的referer字段,后端解析referer字段获取域名进行对比。

——以上内容,如有勘误,欢迎指正!

你可能感兴趣的:(跨域及跨域请求伪造详解)