分布式之跨域解决

一、初探

1、同源策略:阻止一个域的javascript脚本和另外一个域的内容进行交互。同源(即指在同一个域)就是两个页面具有相同的协议(如都是http),域名(如都是www.cat.com,二级域名也不行)和端口号(如都是8080)

2、跨域:一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同

  • http://www.cat.com:8080/user 和 http://www.cat.com:8080/product 属于同源
  • http://www.cat.com:8080/user 和 https://www.cat.com:8080/product 非同源,协议不同
  • http://tao.cat.com:8080/user 和 http://www.cat.com:8080/product 非同源,域名不同
  • http://www.cat.com:8080/user 和 https://www.cat.com:8090/product 非同源,端口不同

二、解决

1、cors解决(以下三种方式):先发出一次OPTIONS的预检请求 Preflighted requests 这个请求是用来验证本次请求是否安全的

1)单个接口注解方式

@CrossOrigin(origins = "http://127.0.0.1:8080")
public ApiResult read(@RequestBody IdDTO dto){//业务代码...}

2)增加一个跨域配置类,允许所有域名进行跨域的方式

public class CorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", crosConfiguration());
        return new CorsFilter(source);
    }

    public CorsConfiguration crosConfiguration(){
        CorsConfiguration config = new CorsConfiguration();
        //允许所有域名进行跨域调用
        config.addAllowedOrigin("*");
        //允许跨越发送cookie
        config.setAllowCredentials(true);
        //放行全部原始头信息
        config.addAllowedHeader("*");
        //允许所有请求方法跨域调用
        config.addAllowedMethod("*");
        return config;
    }
}

3)自定义拦截器的方式

@Component
public class RequestInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler) throws Exception {
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS");
        response.setHeader("Access-Control-Max-Age", "86400");
        response.setHeader("Access-Control-Allow-Headers", "Authorization");
        // 如果是OPTIONS请求则结束
        if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
            response.setStatus(HttpStatus.NO_CONTENT.value());
            return false;
        }
        return true;
    }
}


/** 两个不要同时存在
 * WebMvcConfigurationSupport是springboot2.x版本以上的,1.x版本为WebMvcConfigurerAdapter
 * WebMvcConfigurationSupport-->不需要返回逻辑视图,可以选择继承此类,此法还需在启动类加@EnableWebMvc
 * WebMvcCofigurer-->返回逻辑视图,可以选择实现此方法,重写addInterceptor方法
 * 因为继承WebMvcConfigurationSupport会发现Spring Boot的WebMvc自动配置失效(WebMvcAutoConfiguration自动化配置),导致无法视图解析器无法解析并返回到对应的视图
 */
@Configuration
public class WebConfiguration implements WebMvcConfigurer {
    @Autowired
    private RequestInterceptor requestInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 跨域拦截器
        registry.addInterceptor(requestInterceptor).addPathPatterns("/**");
    }
}
//@Configuration
//public class WebConfiguration extends WebMvcConfigurationSupport {
//    @Resource
//    private RequestInterceptor requestInterceptor;
//    @Override
//    public void addInterceptors(InterceptorRegistry registry) {
//        // 跨域拦截器
//        registry.addInterceptor(requestInterceptor).addPathPatterns("/**");
//    }
//}

2、nginx代理转发解决

  • 先看一下没用nginx转发前的情况,页面和 js中请求接口不同源,接口不允许访问

  • 现在我们配置一下,用同一台主机的nginx来配置代理,这样原来页面和js中的请求域就变成相同的,都是nginx所在的主机,然后利用nginx代理转发的特性来请求到我们真正想访问的地址
server {
    listen       80;
    server_name  localhost;
    location / {
        proxy_pass http://192.168.1.6:8080;
    }
	location /api {
        proxy_pass http://192.168.1.6:8090;
    }
}
  • 接着我们页面和js里代码的访问就需要修改一下,都改成nginx的访问地址,如下,大功告成

3、jsonp方式解决

1) 代码如下

//客户端,三种都可以
$.ajax({
		type: 'GET',
		url: 'http://192.168.1.6:8081/index',
		dataType : "jsonp",//数据类型为jsonp
		jsonp: "jsonpCallback",//服务端用于接收callback调用的function名的参数
		success: function(res) {
			console.log("########" + res);
		},
		error: function(){}
});
/*$.getJSON("http://192.168.1.6:8081/index?jsonpCallback=?",
        function call(){
            console.log();
});*/


//服务端需要打配合
@RestController
public class IndexController {
    @RequestMapping("/index")
    public String index(HttpServletRequest request){
        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("result","index:content");
        String jsonpCallback = request.getParameter("jsonpCallback");
        return jsonpCallback + "(" + jsonObject.toString() + ")";
    }
}

分布式之跨域解决_第1张图片

你可能感兴趣的:(架构)