ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

前后端分离跨域问题的总结

2022-01-02 22:02:35  阅读:139  来源: 互联网

标签:总结 Control http 跨域 分离 Access Allow response


最近由于工作需要,需要java的后端api系统,在搭建过程中遇到了一些跨域问题, 在这里做个简单的总结,以便以后可以参考使用。

  1. 跨域的原因
  2. 我遇到的跨域问题
  3. 如何解决跨域问题
  4. spring Mvc 如何解决跨域
  5. springSecurity 如何解决跨域

1. 跨域的原因

    跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制。
简单的来说就是浏览器栏上的ip,协议,端口和请求的后端ip,协议,端口不一致问题。

举例来说:

http://127.0.0.1:8080 可以调用http://127.0.0.1:8080/api的接口
http://127.0.0.1:8080 不可以调用https://127.0.0.1:8080/api的接口(协议不同)
http://127.0.0.1:8080 不可以调用http://10.0.10.151:8080/api的接口(IP不同)
http://127.0.0.1:8080 不可以调用http://127.0.0.1:8081/api的接口(端口P不同)`

2.我遇到的跨域问题

后端框架:springBoot + SpringSecurity + session
在搭建过程中发现有一下一些问题:
1.前端提示cors错误
2.前端无法set-cookie
3.前段无法读取到Response headers 中的自定义值

3.如何解决跨域问题

在http协议的response header 中有这样几个属性:

Access-control-Allow-Origin:设置允许访问域
Access-control-Allow-Methods:设置允许访问的方法
Access-control-Allow-Header:设置允许访问的请求头
Access-Control-Expose-Headers:设置允许访问的响应头

所以在reponse headers 中写入以下配置就可以解决上述问题1和问题3.

Access-control-Allow-Origin: *
Access-control-Allow-Methods: POST,GET,OPTIONS,DELETE,PUT
Access-control-Allow-Header: token
Access-Control-Expose-Headers: token

这里的token是自定义的header属性名称,不同的项目属性值不同,没有可以不做设置。

关于上述问题2,在尝试了几种方式后都没有很好的解决,所以就将sessionId信息写入到了自定义的header(token)
中返回给前端

4.spring Mvc 如何解决跨域

如果想在Spring mvc项目中设置上述属性,可以加一个Filter


    package cn.web.filter;

    import javax.servlet.*;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    public class CorsFilter implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
        }
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
            response.setHeader("Access-Control-Max-Age", "3600");
            response.setHeader("Access-Control-Allow-Headers", "token");
            response.setHeader("Access-Control-Expose-Headers", "token");
            filterChain.doFilter(servletRequest, servletResponse);
        }
        @Override
        public void destroy() {
        }
    }

不要忘记在web.xml中添加filter相关配置

    <filter>
        <filter-name>crossorigin</filter-name>
        <filter-class>cn.web.filter.CorsFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>crossorigin</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

5.springSecurity 如何解决跨域

  • 方法1:

参考spring Mvc的经验,我们也可以加一个filter

    package com.web.filter;

    import lombok.extern.slf4j.Slf4j;

    import javax.servlet.*;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    @Slf4j
    //@Component
    public class MyCorsFilter implements Filter {

        // @Override
        protected void doFilterInternal(HttpServletRequest servletRequest, HttpServletResponse servletResponse, FilterChain filterChain) throws ServletException, IOException {
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Expose-Headers", "token");
            //Access-Control-Allow-Origin
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
            response.setHeader("Access-Control-Max-Age", "3600");
            response.setHeader("Access-Control-Allow-Headers", "x-requested-with, Lamp-App-Token, content-type");
            filterChain.doFilter(servletRequest, servletResponse);
        }
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            Filter.super.init(filterConfig);
        }
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            doFilterInternal((HttpServletRequest)request,(HttpServletResponse)response,chain);
        }
    
        @Override
        public void destroy() {
            Filter.super.destroy();
        }
    }

将Filter 加入到配置中

    package com.cetc.clp.framework.auth;

    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class FilterConfig {
    
        @Bean
        public FilterRegistrationBean<MyCorsFilter> someFilterRegistration() {
            FilterRegistrationBean<MyCorsFilter> registration = new FilterRegistrationBean<>();
            registration.setFilter(sessionFilter());
            registration.addUrlPatterns("/*");
            registration.setName("MyCorsFilter");
            registration.setOrder(Integer.MIN_VALUE + 50);
            return registration;
        }
    
        @Bean
        public MyCorsFilter sessionFilter(){
            return new MyCorsFilter();
        }
    }
  • 方法2:

    这里还有一种方法是基于spring security框架.

    @Override
    protected void configure(HttpSecurity http) throws Exception {
       ... 
      http.cors().configurationSource(configurationSource());
     ...
    }

    @Bean
	public CorsConfigurationSource configurationSource() {
		UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

		CorsConfiguration config = new CorsConfiguration();
		//config.setAllowCredentials(true);
		//config.setAllowedOriginPatterns(Collections.singletonList("*"));
		config.addAllowedOrigin("*"); //可以放开上面两行,删除这一行,也可以解决跨域问题
		//设置允许访问的方法
		config.setAllowedMethods(Arrays.asList("POST", "OPTIONS", "GET", "DELETE", "PUT"));
		//设置request header允许设置的属性值
		config.addExposedHeader("token");
		config.setAllowedHeaders(Arrays.asList("token"));
        source.registerCorsConfiguration("/**", config);
		return source;
	}

总结:网上有很多相关代码来解决跨域问题,其实不管怎么变化(不包括nigix解决域名的方法),最后都是在reponse header中写入上面几个参数。所以在遇到跨域问题时候,可以检查下代码中是否有以上几个参数设置。

标签:总结,Control,http,跨域,分离,Access,Allow,response
来源: https://www.cnblogs.com/pdata/p/15758448.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有