Java SpringBoot前后端分离跨域配置

最近在做一个新项目,我用的是SpringBoot框架,采用前后端分离方式进行开发,这样在联调的时候就涉及到跨域的问题,通过网上找了很多资料参考,最后整理出来一份可以大家直接拿来使用的代码示例,希望对大家有更多的帮助,本文并不想讲太多的理论,网上讲理论的太多了,直接把代码分享给大家:

1、跨域配置类:

@Configuration
@Slf4j
public class CorsConfig {

    @Bean
    public CorsFilter corsFilter() {
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration config = new CorsConfiguration();
        // 允许cookies跨域
        config.setAllowCredentials(true); 
        // #允许向该服务器提交请求的URI,*表示全部允许,在SpringMVC中,如果设成*,会自动转成当前请求头中的Origin
        config.addAllowedOrigin("*");
        // #允许访问的头信息,*表示全部
        config.addAllowedHeader("*");
        // 预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了
        config.setMaxAge(18000L);
        // 允许提交请求的方法,*表示全部允许
        config.addAllowedMethod("*");

        source.registerCorsConfiguration("/**", config);

        return new CorsFilter(source);
    }

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("*")
                .allowCredentials(true)
                .maxAge(3600);
            }
        };
    }

}

2、进行token校验,在前端进行登录等操作,会进行token的相关校验,针对跨域请求的POST请求,经过断点调试,发现首先会发送【OPTIONS】请求,然后通过之后才会发起真正的POST请求,代码如下:

@Configuration
@WebFilter(urlPatterns = { "/*" }, filterName = "tokenFilter")
@Slf4j
public class TokenFilter implements Filter {

    @Autowired
    private CSMJedisCluster cSMJedisCluster;

    public static List<String> list = Lists.newArrayList();

    static {
        list.add("/csm-web/sys/verificationCode");

        list.add("/csm-web/user/login");
        list.add("/csm-web/user/logout");
        list.add("/csm-web/user/SSORemould");
        list.add("/csm-web/user/getSSOUserInfo");

        list.add("/csm-web/call/reveiveRecord");
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        httpServletResponse.setContentType("application/json;charset=utf-8");
        httpServletResponse.setCharacterEncoding("UTF-8");


        // 得到请求的URL
        String requestURI = httpServletRequest.getRequestURI();

        String method = httpServletRequest.getMethod();

        log.info("------ TokenFilter获取请求接口地址 ------ :【{}】,请求方式:【{}】", requestURI, method);

        // 直接放行
        if (list.contains(requestURI)) {
            log.info("------请求接口:【{}】,不做token校验,TokenFilter直接放行 ------ ",requestURI);
            filterChain.doFilter(request, response);
            return;
        }

        if ("OPTIONS".equals(method)) {
            log.info("------ 请求接口:【{}】,请求方式:【{}】 不做校验,TokenFilter直接放行 ------ ",requestURI,method);
            filterChain.doFilter(request, response);
            return;
        }

        String clientId = httpServletRequest.getHeader("clientId");

        String token = httpServletRequest.getHeader("token");


        log.info("------ TokenFilter获取Header参数 ------:【clientId = {},token = {}】", clientId, token);

        DataResponse responseResult = new DataResponse();

        if(StringUtils.isEmpty(clientId) || StringUtils.isEmpty(token)){
            responseResult.setReturnCode(RespCodeEnum.TOKEN_LOSE.getRespCode());
            responseResult.setMessage("clientId或token参数值为空,请重新登录!");
            handlePrintWriter(httpServletResponse,responseResult);
            return;
        }

        String redisToken = cSMJedisCluster.get(JedisConst.CSM_TOKEN_DATA_CACHE_KEY + Integer.parseInt(clientId));
        log.info("------  TokenFilter ------:【clientId = {},Redis获取该clientId的token = {}】", clientId,redisToken);


        if(StringUtils.isEmpty(redisToken) ){
            responseResult.setReturnCode(RespCodeEnum.TOKEN_LOSE.getRespCode());
            responseResult.setMessage("token已过期,请重新登录!");
            handlePrintWriter(httpServletResponse,responseResult);
            return;
        }

        if(token.equals(redisToken)){
            log.info("------ TokenFilter,请求的token与Redis获取的一致,直接放行------ ");
            filterChain.doFilter(request, response);
            return;
        }else{
            responseResult.setReturnCode(RespCodeEnum.TOKEN_LOSE.getRespCode());
            responseResult.setMessage("token错误,请重新登录!");
            handlePrintWriter(httpServletResponse,responseResult);
            return;
        }

    }

    @Override
    public void destroy() {
    }

    public void handlePrintWriter(HttpServletResponse response, DataResponse result) throws IOException{
        PrintWriter writer =null;
        OutputStreamWriter osw = null;
        try {
            osw = new OutputStreamWriter(response.getOutputStream(), "UTF-8");
            writer = new PrintWriter(osw, true);
            writer.write(JsonUtil.jsonFromObject(result));
            writer.flush();
            writer.close();
            osw.close();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
        if (null != writer) {
            writer.close();
        }
        if (null != osw) {
            osw.close();
        }
    }

    }
}

可能大家的代码写法和思路不一样,可以做为一个参考,希望对大家有所帮助,那讲解的内容就很有意义。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

门主冬七

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值