it编程 > 编程语言 > Java

关于跨域无效的问题及解决(java后端方案)

12人参与 2025-06-10 Java

通用后端跨域方法

1、@crossorigin 注解

在spring boot 中给我们提供了一个注解 @crossorigin 来实现跨域,这个注解可以实现方法级别的细粒度的跨域控制。

我们可以在类或者方添加该注解,如果在类上添加该注解,该类下的所有接口都可以通过跨域访问,如果在方法上添加注解,那么仅仅只限于加注解的方法可以访问。

@slf4j
@restcontroller
@requestmapping(value = apppath.service_location_url + "/appointment")
@api(value = "appointmentcontroller",tags = "预约列表接口")
@crossorigin
public class appointmentcontroller {

    @autowired
    private liveappointmentservice appointmentservice;
	
	@requestmapping
    @apioperation(value = "预约列表分页查询", response = csliveappointmentdto.class)
    public jsonresult<pageinfo> getappointmentlist(appointmentlistdto dto){
        log.info("getappointmentlist vo:{}", jsonutil.tojsonstr(dto));
        pageinfo<csliveappointmentdto> appointmentlist = appointmentservice.getappointmentlist(dto);
        return jsonresult.success(appointmentlist);
    }
}

@crossorigin 注解不生效问题

在spring框架4.2版本后,spring给出了注解的方式解决问题。

即在controller控制器中,在controller注解上方添加@crossorigin注解。

但是使用这种方式后也有可能仍然出现跨域问题,解决方案就是:

@slf4j
@restcontroller
@requestmapping(value = apppath.service_location_url + "/appointment")
@api(value = "appointmentcontroller",tags = "预约列表接口")
@crossorigin
public class appointmentcontroller {

    @autowired
    private liveappointmentservice appointmentservice;

    @apioperation(value = "预约列表分页查询", response = csliveappointmentdto.class)
    //@getmapping("getlist")
    @requestmapping(method = requestmethod.get)
    public jsonresult<pageinfo> getappointmentlist(appointmentlistdto dto){
        log.info("getappointmentlist vo:{}", jsonutil.tojsonstr(dto));
        pageinfo<csliveappointmentdto> appointmentlist = appointmentservice.getappointmentlist(dto);
        return jsonresult.success(appointmentlist);
    }
}

2、springboot2.0 实现webmvcconfigurer 实现跨域

@configuration
public class webmvcconfig implements webmvcconfigurer {
 
    @override
    public void addcorsmappings(corsregistry registry) {
        registry.addmapping("/**")
                .allowedorigins("*")
                .allowedmethods("post","get","options")
                .allowedheaders("*")
                .allowcredentials(false).maxage(3600);
    }
 
}
 

3、过滤器实现跨域

@webfilter(filtername = "corsfilter")
@configuration
@order(ordered.highest_precedence)
@slf4j
public class corsfilter implements filter {

    @value("${allow.headers:x-requested-with,authorization,content-type}")
    private string allowheaders;

    @value("${allow.origin:https://xxx.com}")
    private string alloworigin;

    @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-origin", "http://xxx:9091");
        response.setheader("access-control-allow-credentials", "true");
        response.setheader("access-control-allow-methods", "post, get, patch,options, delete, put");
        response.setheader("access-control-max-age", "3600");
        response.setheader("access-control-allow-headers", allowheaders);
//        response.setheader("access-control-allow-headers", "*");
        log.info("corsfilter res {},{}", response.getheader("access-control-allow-origin"), response.containsheader("access-control-allow-origin"));
        chain.dofilter(req, res);
    }
}

跨域不生效问题 

(1)、@order(ordered.highest_precedence)如果有登录拦截,要将跨域filter等级提升为最高优先级 

(2)、 response.setheader(“access-control-allow-headers”, “");

(3)、 response.setheader(“access-control-allow-origin”, "”)

//指定允许其他域名访问
‘access-control-allow-origin:http://172.80.0.206'//一般用法(,指定域,动态设置),3是因为不允许携带认证头和cookies
//是否允许后续请求携带认证信息(cookies),该值只能是true,否则不返回

(4)、 response.setheader(“access-control-allow-methods”, “post, get, patch,options, delete, put”);options 在预检请求复杂请求中也会使用到 

(5)、 如果有spring security结合使用需要添加该过滤器

@configuration
public class securityconfig extends websecurityconfigureradapter {
 
    @override
    protected void configure(httpsecurity security) throws exception {
        security.csrf().disable();
        security.headers().frameoptions().disable();
        //加入过滤器
        security.addfilterbefore(new corsfilter(), 			             	usernamepasswordauthenticationfilter.class);
    }
}

4、定制化参数实现跨域

前面要么是*,实际需求是根据业务参数定制化

@webfilter(filtername = "corsfilter", urlpatterns = "/*",
        initparams = {@webinitparam(name = "alloworigin", value = "*"),
                @webinitparam(name = "allowmethods", value = "get,post,put,delete,options"),
                @webinitparam(name = "allowcredentials", value = "true"),
                @webinitparam(name = "allowheaders", value = "content-type,x-token")})
public class corsfilter implements filter {
 
    private string alloworigin;
    private string allowmethods;
    private string allowcredentials;
    private string allowheaders;
    private string exposeheaders;
 
    @override
    public void init(filterconfig filterconfig) throws servletexception {
        alloworigin = filterconfig.getinitparameter("alloworigin");
        allowmethods = filterconfig.getinitparameter("allowmethods");
        allowcredentials = filterconfig.getinitparameter("allowcredentials");
        allowheaders = filterconfig.getinitparameter("allowheaders");
        exposeheaders = filterconfig.getinitparameter("exposeheaders");
    }
 
    @override
    public void dofilter(servletrequest servletrequest, servletresponse servletresponse, filterchain filterchain) throws ioexception, servletexception {
        httpservletrequest request = (httpservletrequest) servletrequest;
        httpservletresponse response = (httpservletresponse) servletresponse;
        if (!stringutils.isempty(alloworigin)) {
            if(alloworigin.equals("*")){
                // 设置哪个源可以访问
                response.setheader("access-control-allow-origin", alloworigin);
            }else{
                list<string> alloworiginlist = arrays.aslist(alloworigin.split(","));
                if (alloworiginlist != null && alloworiginlist.size() > 0) {
                    string currentorigin = request.getheader("origin");
                    if (alloworiginlist.contains(currentorigin)) {
                        response.setheader("access-control-allow-origin", currentorigin);
                    }
                }
            }
        }
        if (!stringutils.isempty(allowmethods)) {
            //设置哪个方法可以访问
            response.setheader("access-control-allow-methods", allowmethods);
        }
        if (!stringutils.isempty(allowcredentials)) {
            // 允许携带cookie
            response.setheader("access-control-allow-credentials", allowcredentials);
        }
        if (!stringutils.isempty(allowheaders)) {
            // 允许携带哪个头
            response.setheader("access-control-allow-headers", allowheaders);
        }
        if (!stringutils.isempty(exposeheaders)) {
            // 允许携带哪个头
            response.setheader("access-control-expose-headers", exposeheaders);
        }
        filterchain.dofilter(servletrequest, servletresponse);
    }
 
    @override
    public void destroy() {
 
    }
}

5、 使用springcloud网关gateway实现跨域

原理和前面类似

import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
import org.springframework.web.cors.corsconfiguration;
import org.springframework.web.cors.reactive.corswebfilter;
import org.springframework.web.cors.reactive.urlbasedcorsconfigurationsource;
import org.springframework.web.util.pattern.pathpatternparser;

@configuration
public class corsconfig {
    @bean
    public corswebfilter corsfilter() {
        corsconfiguration config = new corsconfiguration();
        config.setallowcredentials(boolean.true);//允许cookie跨域
        config.addallowedmethod("*");
        config.addallowedorigin("*");
        config.addallowedheader("*");//不要设置成*,参考前面

        urlbasedcorsconfigurationsource source = new urlbasedcorsconfigurationsource(new pathpatternparser());
        source.registercorsconfiguration("/**", config);

        return new corswebfilter(source);
    }
}

:在下层服务不需要在做任何跨域配置,例如注解@crossorigin,否则会由于配置冲突导致依然出现跨域问题

6、nginx配置代理解决跨域问题

server {
        listen       8000;
        server_name  localhost;
        # / 表示匹配路径为/的url
        location / {
           proxy_pass http://需要跨域的域名:5500;
        }
 
        # /user 表示访问以/user 开头 的地址 如/username,/user/find等
        location /user {
           proxy_pass http://需要跨域的域名:3000;
        }
 
    }

7、nginx配置响应头允许跨域

#
# wide-open cors config for nginx
#
location / {
	
	#### 对options请求,会设置很多的请求头,并返回204
     if ($request_method = 'options') {
        add_header 'access-control-allow-origin' '*';
        add_header 'access-control-allow-methods' 'get, post, options';
        #
        # custom headers and headers various browsers *should* be ok with but aren't
        #
        add_header 'access-control-allow-headers' 'dnt,user-agent,x-requested-with,if-modified-since,cache-control,content-type,range';
        #
        # tell client that this pre-flight info is valid for 20 days
        #
        add_header 'access-control-max-age' 1728000;
        add_header 'content-type' 'text/plain; charset=utf-8';
        add_header 'content-length' 0;
        return 204;
     }
     if ($request_method = 'post') {
        add_header 'access-control-allow-origin' '*';
        add_header 'access-control-allow-methods' 'get, post, options';
        add_header 'access-control-allow-headers' 'dnt,user-agent,x-requested-with,if-modified-since,cache-control,content-type,range';
        add_header 'access-control-expose-headers' 'content-length,content-range';
     }
     if ($request_method = 'get') {
        add_header 'access-control-allow-origin' '*';
        add_header 'access-control-allow-methods' 'get, post, options';
        add_header 'access-control-allow-headers' 'dnt,user-agent,x-requested-with,if-modified-since,cache-control,content-type,range';
        add_header 'access-control-expose-headers' 'content-length,content-range';
     }
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

您想发表意见!!点此发布评论

推荐阅读

Java SWT库详解与安装指南(最新推荐)

06-10

maven私服配置全过程

06-10

使用SpringBoot整合Sharding Sphere实现数据脱敏的示例

06-10

Java的内存泄漏和性能瓶颈解读

06-10

如何在Java中使用org.json和JSON-B解析与编写JSON

06-10

SpringCloudGateway 自定义局部过滤器场景分析

06-10

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论