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();
        }
    }

    }
}

可能大家的代碼寫法和思路不一樣,可以做爲一個參考,希望對大家有所幫助,那講解的內容就很有意義。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章