一个界面发起的ajax请求,只能是当前页面同域名发起的,这样就可以有效避免黑客发起的对服务器的恶意攻击;
请求跨域了,那么请求到底发出去没有?
跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。你可能会疑问明明通过表单的方式可以发起跨域请求,为什么 Ajax 就不会?因为归根结底,跨域是为了阻止用户读取到另一个域名下的内容,Ajax 可以获取响应,浏览器认为这不安全,所以拦截了响应。但是表单并不会获取新的内容,所以可以发起跨域请求。同时也说明了跨域并不能完全阻止 CSRF,因为请求毕竟是发出去了。
a网站向b网站请求1.js文件时,向b网站发送一个获取的请求,nginx根据配置文件接收这个请求,代替a网站向b网站来请求这个资源,nginx拿到这个资源后再返回给a网站,以此来解决了跨域问题。
例子:
server { #监听8000端口 listen 8000; #监听指定的ip地址 server_name 10.10.2.116; #对对应url路径执行反向代理,如10.10.2.116:8000/demo location /demo { #目标的ip地址 proxy_pass http://www.leyou.com; } }缺点: 需要的nginx进行额外配置;
规范的跨域请求解决方案,安全可靠:
优点: 在服务端进行控制是否允许跨域,可以自定义规则,如header,method,origin,自定义限制;
缺点: 会产生额外的请求;
1.请求方式的区分:head,put,post;
2.头信息的限制:
Accept Accept-Language Content-Language Last-Event-ID Content-Type:只限于三个值 application/x-www-form-urlencoded、multipart/form-data、text/plain
发送简单请求时 浏览器会自动识别并携带字段 origin =www.leyou.com,服务器会根据这个值进行判定是否允许跨域
不满足简单请求条件则就是复杂请求
浏览器想服务端发送预检请求:
OPTIONS /cors HTTP/1.1 Origin: http://manage.leyou.com Access-Control-Request-Method: PUT Access-Control-Request-Headers: X-Custom-Header Host: api.leyou.com Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0...服务端收到预检请求后,如果允许跨域,会发出响应:
HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 01:15:39 GMT Server: Apache/2.0.61 (Unix) Access-Control-Allow-Origin: http://manage.leyou.com Access-Control-Allow-Credentials: true Access-Control-Allow-Methods: GET, POST, PUT Access-Control-Allow-Headers: X-Custom-Header Access-Control-Max-Age: 1728000 Content-Type: text/html; charset=utf-8 Content-Encoding: gzip Content-Length: 0 Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Content-Type: text/plain服务端返回自己对跨域的请求的要求限制:
- Access-Control-Allow-Origin:可接受的域,是一个具体域名或者*,代表任意 - Access-Control-Allow-Methods:允许访问的方式 - Access-Control-Allow-Headers:允许携带的头 - Access-Control-Max-Age:本次许可的有效时长,单位是秒 允许客户端可以携带Cookie - Access-Control-Allow-Credentials:是否允许携带cookie,默认情况下,cors不会携带cookie,除非这个值是true
客户端跨域想要携带COOKIE要满足的要求:
- 服务的响应头中需要携带Access-Control-Allow-Credentials并且为true。 - 浏览器发起ajax需要指定withCredentials 为true - 响应头中的Access-Control-Allow-Origin一定不能为*,必须是指定的域名
实际操作:
需要的配置一个Bean ,CorsFilter 过滤类 包含 UrlBasedCorsConfigurationSource----》 1.path:对映射路径的限制 2.CorsConfiguration---》封装了对跨域请求的限制,origin,header,method的设置; CorConfiguration 封装对跨域请求的限制:允许的域,不要写*,否则cookie就无法使用了 config.addAllowedOrigin("http://manage.leyou.com"); config.addAllowedOrigin("http://www.leyou.com"); 允许的请求方式 config.addAllowedMethod("OPTIONS"); config.addAllowedMethod("HEAD"); config.addAllowedMethod("GET"); config.addAllowedMethod("PUT"); config.addAllowedMethod("POST"); config.addAllowedMethod("DELETE"); config.addAllowedMethod("PATCH"); 允许的头信息 config.addAllowedHeader("*"); 是否发送Cookie信息 config.setAllowCredentials(true); 添加映射路径,我们拦截一切请求 UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource(); configSource.registerCorsConfiguration("/**", config); 返回新的CorsFilter. return new CorsFilter(configSource);
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; @Configuration public class GlobalCorsConfig { @Bean public CorsFilter corsFilter() { //1.添加CORS配置信息 CorsConfiguration config = new CorsConfiguration(); //1) 允许的域,不要写*,否则cookie就无法使用了 config.addAllowedOrigin("http://manage.leyou.com"); config.addAllowedOrigin("http://www.leyou.com"); //2) 是否发送Cookie信息 config.setAllowCredentials(true); //3) 允许的请求方式 config.addAllowedMethod("OPTIONS"); config.addAllowedMethod("HEAD"); config.addAllowedMethod("GET"); config.addAllowedMethod("PUT"); config.addAllowedMethod("POST"); config.addAllowedMethod("DELETE"); config.addAllowedMethod("PATCH"); // 4)允许的头信息 config.addAllowedHeader("*"); //2.添加映射路径,我们拦截一切请求 UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource(); configSource.registerCorsConfiguration("/**", config); //3.返回新的CorsFilter. return new CorsFilter(configSource); } }