SpringBoot解决跨域问题

1.什么是跨域问题呢?

跨域指的是不同的站点之间,用ajax没办法相互进行调用的问题。它的本质是浏览器的一种保护机制。它其实就是为了保证用户的安全,防止出现恶意网站盗取数据。但是,这个保护机制也带了新问题:不同站点之间的正常调用有阻碍障碍。

2.跨域的几种情况

(1)请求协议不同

(2)域名不同

(3)端口不同

我们在使用过程中,出现了上面的任意一种情况都属于跨域问题。包括如果说域名一样,但是请求协议不一样也是跨域问题。

常见的跨域如下所示:

当前url 被请求的url 是否跨域
http://www.nflang.com/ http://www.nflang.com/login.html
http://www.nflang.com/ https://www.nflang.com/login.html
http://www.nflang.com/ http://www.nflang1.com/
http://www.nflang.com/ http://blog.nflang.com/
http://www.nflang.com:8080/ http://www.nflang.com:8091/

我们一般会有一个前端项目、一个后端项目,两个服务端口不一样,前端项目端口8081,后端项目8080。前端项目在调用后端接口时候会出现跨域问题。

SpringBoot解决跨域问题_第1张图片

 下面呢给大家提供几种解决办法:

(1)使用 @CrossOrigin 注解实现跨域;

使用 @CrossOrigin 注解可以轻松的实现跨域,此注解既可以修饰类,也可以修饰方法。当修饰类时,表示此类中的所有接口都可以跨域;当修饰方法时,表示此方法可以跨域。代码实现如下:

package com.test.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.nimbusds.jose.JWSObject;


@RestController
@CrossOrigin(origins = "*")
@RequestMapping("/login")
public class LoginController {
     @Autowired
     private SysUserService sysUserService;


    /**
     * 登录
     */
    @PostMapping("/userLogin")
    @ApiOperation(value = "校验登录账号", response = ApiResult.class)
    public ApiResult userLogin(@RequestBody SysUserQueryVo sysUserQueryVo){
        try {
            ApiResult apiResult = sysUserService.userLogin(sysUserQueryVo);
            System.out.println("测试登录");
            return apiResult;
        } catch (Exception e) {
            log.info("用户登录失败"+e.getMessage());
            throw new DaoException("用户登录失败"+e.getMessage());
        }
    }

   
}

(2)通过配置文件实现跨域;

  • 创建一个新配置文件;

  • 添加 @Configuration 注解,实现 WebMvcConfigurer 接口;

  • 重写 addCorsMappings 方法,设置允许跨域的代码。、

代码实现如下所示:

package com.test.config;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration 
public class MyCorsFilter {
    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        //开放哪些ip、端口、域名的访问权限,星号表示开放所有域
        config.addAllowedOrigin("*");
        //是否允许发送Cookie信息
        config.setAllowCredentials(true);
        //开放哪些Http方法,允许跨域访问
        config.addAllowedMethod("*");
        //允许HTTP请求中的携带哪些Header信息
        config.addAllowedHeader("*");
        //暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
       // config.addExposedHeader("*");

        config.addExposedHeader("Content-Type");
        config.addExposedHeader( "X-Requested-With");
        config.addExposedHeader("accept");
        config.addExposedHeader("Origin");
        config.addExposedHeader( "Access-Control-Request-Method");
        config.addExposedHeader("Access-Control-Request-Headers");

        //添加映射路径,“/**”表示对所有的路径实行全局跨域访问权限的设置
        UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
        configSource.registerCorsConfiguration("/**", config);

        return new CorsFilter(configSource);}
}

(3)通过 CorsFilter 对象实现跨域;

该实现方式和(2)里面的实现方式类似,他也能够实现全局跨域。

代码实现如下所示:

package com.test.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
 
@Configuration 
public class MyCorsFilter {
    @Bean
    public CorsFilter corsFilter() {
        // 1.创建 CORS 配置对象
        CorsConfiguration config = new CorsConfiguration();
        // 支持域
        config.addAllowedOriginPattern("*");
        // 是否发送 Cookie
        config.setAllowCredentials(true);
        // 支持请求方式
        config.addAllowedMethod("*");
        // 允许的原始请求头部信息
        config.addAllowedHeader("*");
        // 暴露的头部信息
        config.addExposedHeader("*");
        // 2.添加地址映射
        UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
        corsConfigurationSource.registerCorsConfiguration("/**", config);
        // 3.返回 CorsFilter 对象
        return new CorsFilter(corsConfigurationSource);
    }
}

(4)通过 Response 对象实现跨域;

该方式属于最原始的一种方式,但是它能够支持任意的版本的 Spring Boot(早期的 Spring Boot 版本也是支持的)。但此方式也是局部跨域,它应用的范围最小,设置的是方法级别的跨域。

代码实现如下:

com.test.login

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
 
@RestController
public class LoginController {
    @RequestMapping("/test")
    public HashMap test(HttpServletResponse response) {
        // 设置跨域
        response.setHeader("Access-Control-Allow-Origin", "*");
        return new HashMap() {{
            put("state", 200);
            put("data", "success");
            put("msg", "");
        }};
    }
}

(5)通过实现 ResponseBodyAdvice 实现跨域。

通过重写 ResponseBodyAdvice 接口中的 beforeBodyWrite(返回之前重写)方法,我们可以对所有的接口进行跨域设置。它也是实现的全局跨域,对整个项目的接口全部有效。

它的具体实现代码如下:

com.test.config

import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
 
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
    /**
     * 内容是否需要重写
     * 返回 true 表示重写
     */
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }
    /**
     * 方法返回之前调用此方法
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                  Class selectedConverterType, ServerHttpRequest request,
                                  ServerHttpResponse response) {
        // 设置跨域
        response.getHeaders().set("Access-Control-Allow-Origin", "*");
        return body;
    }
}

你可能感兴趣的:(项目常见工具类及问题分享,spring,boot,后端,java)