背景

最近在基于大模型做一个前后端分离的小项目,主要是支持用户自定义自己的机器人。我是负责后端开发,使用SpringBoot开发,前端是另外一个专门负责开发前端的大佬在开发。

这里就有一个问题,我后端接口的ip和端口与前端不同,也不可能相同,这就会形成跨域问题了。

什么是跨域呢?
跨域:协议,主机地址,端口,这三者有一个不同,都会形成跨域。

2. 解决跨域

2.1 SpringBoot中解决跨域

2.1.1 配置文件方式

配置文件中写入下面的代码:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
                .allowCredentials(true)
                .maxAge(3600)
                .allowedHeaders("*");
    }
}

其中allowedOrigins设置允许哪些主机可以跨域访问

addMapping设置访问哪些接口可以跨域

allowCredentials设置是否可以跨域传递Cookie

2.1.2 拦截器方式

public class CrossInterceptorHandler implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        response.setHeader("Access-Control-Allow-Origin", "http://192.168.1.105");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET , PUT , OPTIONS");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with,accept,authorization,content-type");
        return true;
    }

}

然后记得在配置文件中注入

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new CrossInterceptorHandler()).addPathPatterns("/**");
    }
}

2.1.3 过滤器方式

import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter(filterName = "CorsFilter ")
@Configuration
public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin","*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        chain.doFilter(req, res);
    }
}

2.1.4 注解方式

@CrossOrigin(origins = "http://192.168.105:8848")

这种方式颗粒度更细,可以控制到每个接口的访问,也可以在需要跨域访问的类上添加这个注解。

2.2 Nginx方式解决跨域

nginx.conf中配置反向代理,配置如下:

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    server {
        listen       80;
        server_name  tosim.top;

        location / {
                root html/build;
                try_files $uri /index.html;  # try_files:检查文件; $uri:监测的文件路径; /index.html:文件不存在重定向的新路径 
                index index.html; 
        }

        location /api/ {
            # 把 /api 路径下的请求转发给真正的后端服务器
            proxy_pass http://localhost:8080/;

            # 把host头传过去,后端服务程序将收到your.domain.name, 否则收到的是localhost:18080
            proxy_set_header Host $http_host;

            # 把cookie中的path部分从/api替换成/service
            proxy_cookie_path /api /;

            # 把cookie的path部分从localhost:18080替换成your.domain.name
            proxy_cookie_domain localhost:18080 tosim.top;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

3. 总结

这里列举了两大类解决前后端项目中的跨域问题,一种是在后端进行处理,另外一种是中间件进行处理。那么除了这两种方式,还有没有其它方式解决呢?比如在前端中解决跨域问题,也欢迎大家在评论区讨论。

更多内容,欢迎访问我的博客

Q.E.D.


热爱生活,热爱程序