Nginx跨域请求配置

109次阅读
没有评论

一、概念

由于浏览器启用了同源策略(同源,指的是协议,域名,端口相同。浏览器处于安全方面的考虑,只允许本域名下的接口交互,不能读写不同源的资源。),我们在开发当中经常遇到跨域请求的情况。那什么是跨域请求呢?

不同源的请求既是跨域请求,例如:

https://www.baidu.com向http://www.baidu.com发起请求,https协议与http协议不同

https://www.baidu.com向https://www.baidu.com:8080发起请求,端口号不同,一个是80,一个是8080

https://www.baidu.com向https://www.google.com发起请求,域名不同

以上任意一种或多种情况,都会导致跨域请求。

二、解决办法

1、第一种方法,网络上盛传,我试了没用。在Nginx的server下配置:

server{

其他配置……

add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';

其他配置……

}

2、通过前后端配置

那么我遇到的问题是协议与端口号都不同,因为我的Java程序部署到服务器没有https,也没有80端口,从而产生了跨域问题。解决办法是在Nginx配置一个反向代理路径,并且后端允许跨域请求。

使用的框架是:后端:spring boot 2.5.5,前端用的是Nginx做反向代理访问。

第一步:配置Nginx

server{

其他配置……

location /test
{
root html;
#添加下面的一句话
proxy_pass http://127.0.0.1:8080;
index index.html index.htm;
}

其他配置……

}

注意:这里要加在server里面,监听端口应该是80,这样当我们发起请求的时候可以使用前端的https和80端口。翻译过来就是我们请求https://www.baidu.com/test的时候,实际上请求的是http://127.0.0.1:8080/test。当然这里的http://127.0.0.1:8080还可以是其他地址,假如你的后端部署在其他服务器上,那么对应的就是其他服务器地址。

第二步:配置后端允许跨域

那么接下来就是后端配置,后端配置是在拦截器出加上允许跨域请求配置。直接贴代码

拦截器配置类:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @author:
 * @create: 2023-01-19 23:15
 * @Description: 拦截器配置类
 */
@Configuration
public class InterceptorConfiguration implements WebMvcConfigurer {


    /**
     * 重写addCorsMappings()解决跨域问题
     * 配置:允许http请求进行跨域访问
     *
     * @param registry
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        //指哪些接口URL需要增加跨域设置
        registry.addMapping("/**")
                //.allowedOrigins("*")//指的是前端哪些域名被允许跨域
                .allowedOriginPatterns("*")
                //需要带cookie等凭证时,设置为true,就会把cookie的相关信息带上
//                .allowCredentials(true)
                //指的是允许哪些方法
                .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
                //cookie的失效时间,单位为秒(s),若设置为-1,则关闭浏览器就失效
//                .maxAge(3600)
        ;
    }

    /**
     * 重写addInterceptors()实现拦截器
     * 配置:要拦截的路径以及不拦截的路径
     *
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //注册Interceptor拦截器(Interceptor这个类是我们自己写的拦截器类)
        InterceptorRegistration registration = registry.addInterceptor(new Interceptor());
        registration.excludePathPatterns();
    }
}


拦截器:

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.Date;

/**
 * 拦截器
 */

@Slf4j
@Component
public class Interceptor implements HandlerInterceptor {


    /**
     * 在请求处理之前进行调用(Controller方法调用之前)
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        return true;//如果设置为false时,被请求时,拦截器执行到此处将不会继续操作
        //如果设置为true时,请求将会继续执行后面的操作
    }

    /**
     * 访问控制器方法后执行
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        System.out.println(new Date() + "--postHandle:" + request.getRequestURL());
    }

    /**
     * postHandle方法执行完成后执行,一般用于释放资源
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println(new Date() + "--afterCompletion:" + request.getRequestURL());
    }
}

这样当我们请求后端接口,比如https://www.baidu.com/test/temp时,就会直接请求到我们的后端接口。

正文完
 
评论(没有评论)