解决跨域问题
前言
跨域问题,是web开发绕不开的难题首先要认识这几点
1.跨域是只存在与浏览器端,不存在与其他环境如:安卓/iso/js/java等其他环境.
2.跨域请求能发出去,服务端能收到请求并正常的返回结果,只是结果被浏览器拦截了.
之所以会跨域是,因为受到了同源策略的限制,同源政策是一种约定,是浏览器的核心也是最基本的安全功能
同源的内容有: 域名 , 协议 , 端口
浏览器出于安全的考虑,使用 XMLHttpRequest对象发起 HTTP请求时必须遵守同源策略,否则就是跨域的HTTP请求,默认情况下是被禁止的。换句话说,浏览器安全的基石是同源策略。
浏览器出于安全的考虑,使用 XMLHttpRequest对象发起 HTTP请求时必须遵守同源策略,否则就是跨域的HTTP请求,默认情况下是被禁止的。换句话说,浏览器安全的基石是同源策略。
什么是CROS?
CORS是一个W3C标准,全称是”跨域资源共享”(Cross-origin resource sharing),允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。它通过服务器增加一个特殊的Header[Access-Control-Allow-Origin]来告诉客户端跨域的限制,如果浏览器支持CORS、并且判断Origin通过的话,就会允许XMLHttpRequest发起跨域请求。
CORS Header
- Access-Control-Allow-Origin:
http://localhost:8080
- Access-Control-Max-Age:86400
- Access-Control-Allow-Methods:GET, POST, OPTIONS, PUT, DELETE
- Access-Control-Allow-Headers: content-type
- Access-Control-Allow-Credentials: true
含义解释:
1、Access-Control-Allow-Origin 允许http://localhost:8080
域(自行设置,这里只做示例)发起跨域请求
2、Access-Control-Max-Age 设置在86400秒不需要再发送预校验请求
3、Access-Control-Allow-Methods 设置允许跨域请求的方法
4、Access-Control-Allow-Headers 允许跨域请求包含content-type
5、Access-Control-Allow-Credentials 设置允许Cookie
filtr(过滤器) 方式解决跨域
在项目中添加Filter类:
package com.zx.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class AllowOriginFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO 其他处理
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 强转为httpRequest
HttpServletRequest request = (HttpServletRequest) servletRequest;
// 强转为httpResponse
HttpServletResponse response = (HttpServletResponse) servletResponse;
// 获取请求头中的 Origin:起源
String origin = request.getHeader("Origin");
if (origin != null && origin != "") {
//设置响应头,允许跨域访问
//带cookie请求时,必须为全匹配,不能使用*
/**
* 表示允许 origin 发起跨域请求。
*/
response.addHeader("Access-Control-Allow-Origin", origin);
/**
* GET,POST,OPTIONS,PUT,DELETE 表示允许跨域请求的方法
*/
response.addHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, DELETE");
/**
* 表示在86400秒内不需要再发送预校验请求
*/
response.addHeader("Access-Control-Max-Age", "86400");
//支持所有自定义头
String headers = request.getHeader("Access-Control-Request-Headers");
if (headers != null && headers != "") {
//允许JSON请求,并进行预检命令缓存
response.addHeader("Access-Control-Allow-Headers", headers);
}
response.addHeader("Access-Control-Max-Age", "3600");
//允许cookie
response.addHeader("Access-Control-Allow-Credentials", "true");
filterChain.doFilter(servletRequest, response);
}
}
@Override
public void destroy() {
// TODO 其他处理
}
}
Springboot中解决跨域
两种方法解决跨域问题
在SpringBoot项目中,推崇的都是约定优先于配置,尽量少使用配置
一. 注入重写方法 (WebMvcConfigurer)
在解决跨越的问题上,只需要进行一个对象,对其进行重写方法即可
整个Application的handler允许跨域
package com.zx.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CORSConfig {
@Bean
public WebMvcConfigurer corsConfigurer(){
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry){
registry.addMapping("/**") // 添加映射
.allowedHeaders("*") //允许的标头
.allowedMethods("*") //允许的方法
.allowedOrigins("*"); //允许的起源
}
};
}
}
二. @CrossOrigin
介绍:
只需要在允许跨域的接口方法上进行添加注解即可,也可以直接在Controller类上添加,表示该Controller所有方法均允许跨域访问。
1. @CrossOrigin写在方法上
您可以添加到@RequestMapping . unk处理方法一个@ crosssource注释,以便在它上启用CORS(默认的@CrossOrigin允许@RequestMapping注释中指定的所有起源和HTTP方法):
package com.zx.controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/admin")
public class AdminController {
@CrossOrigin
@GetMapping("/test")
public void test(){
System.out.println("你好");
}
}
2.@CrossOrigin写在类上
为整个控制器启用CORS:
package com.zx.controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/admin")
@CrossOrigin(origins = "http://localhost:80",maxAge = 3600)
public class AdminController {
@GetMapping("/test")
public void test(){
System.out.println("你好");
}
}
Nginx 中跨域解决
Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。
其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、简单的配置文件和低系统资源的消耗而闻名。
反向代理
反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。
要求
确认服务器端是没有处理跨域
跨域主要涉及的四个响应头
- Access-Control-Allow-Origin
用于设置允许跨域请求源地址(预检请求和正式请求在跨域时候都会验证)
- Access-Control-Allow-Headers
跨域允许携带的特殊信息字段(只在预检请求验证)
- Access-Control-Allow-Methods
跨域允许的请求方式或者说HTTP动词(只是预检请求验证)
- Access-Control-Allow-Credentials
是否允许跨域使用cookies,如果要跨域使用cookies,可以添加上此请求响应头,值设为true(设置或者不设置,都不会影响请求发送,只会影响在跨域时候是否要携带cookies,但是如果设置,预检请求和正式请求都需要设置)。不过不建议跨域使用(项目中用到过,不过不稳定,有些浏览器带不过去),除非必要,因为有很多方案可以代替。
nginx配置文件
upstream zx.com {
# weight 分量 代表分给该端口的分量
server localhost:8081 weight=1;
server localhost:8082 weight=2;
server localhost:8083 weight=3;
server localhost:8084 weight=4;
# backup 后备 后备隐藏能源
server localhost:8085 backup;
server localhost:8086 backup;
}
server {
listen 8088;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
# 解决跨域问题
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers X-Requested-With;
add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
proxy_pass http://zx.com;
}
# * location / {
# root html;
# index index.html index.htm;
# }
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
nginx的cmd命令
- 启动服务: start nginx
- 退出服务: nginx -s quit
- 强制关闭服务: nginx -s stop
- 重载服务: nginx -s reload (重载服务配置文件,类似重启,服务不会终止)
- 验证配置文件: nginx -t
- 使用配置文件: nginx -c “配置文件路径”
- 使用帮助: nginx -h
注: 可以通过DOS命令服务:也可以直接双击nginx.exe启动服务;