使用Filter拦截器如何实现请求跨域转发

 更新时间:2021年08月28日 11:37:28   作者:成都杨小天  
这篇文章主要介绍了使用Filter拦截器如何实现请求跨域转发,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

Filter拦截器实现请求跨域转发

因为公司项目需求,项目中前端请求需要通过一个类似中转的服务转发(请求在该服务中会重新包装一些通用参数)

在使用Filter实现转发后特做一次记录

package com.unicloud.cce.Filter; 
import com.alibaba.fastjson.JSON;
import com.unicloud.cce.common.RestfulEntity;
import com.unicloud.cce.service.CloudosService;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate; 
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
 
/**
 * @author skyxt
 * Created 2019-06-11 18:46
 * Email skyxt.yang@gmail.com
 */
@WebFilter(filterName = "authFilter", urlPatterns = { "/*" })
@Component
public class RequestFilter implements Filter { 
 
    //该处配置需要转发的路径
    public static final Set<String> FILTER_URL = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
            "/config/*"
    )));
 
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private CloudosService cloudosService;  
    private final static Logger logger = LoggerFactory.getLogger(RequestFilter.class); 
    @Override
    public void init(FilterConfig filterConfig) throws ServletException { 
    }
 
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        if (!(request instanceof HttpServletRequest) || !(response instanceof HttpServletResponse)) {
            return;
        }
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse rsp = (HttpServletResponse) response;
        AntPathMatcher matcher = new AntPathMatcher();
        Optional<String> cloudIp = Optional.empty();
//        for (String url : FILTER_URL) {
//            if (matcher.match(url, req.getRequestURI().substring(req.getContextPath().length()))) {
//                cloudIp = cloudosService.cloudosList("", "").stream().filter(cloudos ->
//                        cloudos.getId().equals(((HttpServletRequest) request).getHeader("cloudId"))
//                ).map(Cloudos::getCloudIp).findFirst();
//            }
//        }
        cloudIp = Optional.of("localhost");
        if (cloudIp.isPresent()) {
            switch (req.getMethod()) {
                case "GET": {
                    request(req, rsp, HttpMethod.GET, cloudIp.get());
                    break;
                }
                case "POST": {
                    request(req, rsp, HttpMethod.POST, cloudIp.get());
                    break;
                }
                case "PUT": {
                    request(req, rsp, HttpMethod.PUT, cloudIp.get());
                    break;
                }
                case "PATCH": {
                    request(req, rsp, HttpMethod.PATCH, cloudIp.get());
                    break;
                }
                case "DELETE": {
                    request(req, rsp, HttpMethod.DELETE, cloudIp.get());
                    break;
                }
                default:{
                    logger.error("unknow request method:" + req.getMethod());
                    rsp.setCharacterEncoding("UTF-8");
                    try (PrintWriter out = rsp.getWriter()) {
                        out.write("请求方法未知");
                    } catch (Exception e1) {
                        logger.error(e1.getMessage() + e1);
                    }
                } 
            }
        } else {
            chain.doFilter(request, response);
        }
    }
 
    @Override
    public void destroy() { 
    }
 
    private void request(HttpServletRequest req, HttpServletResponse rsp, HttpMethod method, String cloudIp) throws IOException {
        rsp.setCharacterEncoding("UTF-8");
        String requestBody = IOUtils.toString(req.getInputStream(), "UTF-8");
        Object body = null;
        if (StringUtils.hasText(requestBody)) {
            body = JSON.parse(requestBody);
        }
        HttpHeaders headers = new HttpHeaders();
        Enumeration<String> headerNames = req.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String name = headerNames.nextElement();
            headers.add(name, req.getHeader(name));
        }
        String url;
        if (StringUtils.hasText(req.getQueryString())) {
            url = String.format(
                    "http://%s:15120%s?%s",
                    cloudIp,
                    req.getRequestURI().substring(req.getContextPath().length()),
                    req.getQueryString()
                    );
        } else {
            url = String.format(
                    "http://%s:15120%s",
                    cloudIp,
                    req.getRequestURI().substring(req.getContextPath().length())
            );
        }
        HttpEntity<Object> httpEntity = new HttpEntity<>(body, headers);
        ResponseEntity<RestfulEntity> exchange = null;
        try {
            exchange = restTemplate.exchange(
                    url,
                    method,
                    httpEntity,
                    RestfulEntity.class
            );
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            try (PrintWriter out = rsp.getWriter()) {
                out.write("请求异常");
            } catch (Exception e1) {
                logger.error(e1.getMessage() + e1);
            }
        }
        if (exchange != null) {
            exchange.getStatusCode();
            rsp.setStatus(exchange.getStatusCodeValue());
            exchange.getHeaders().entrySet().stream().forEach(entry -> {
                String value = entry.getValue().toString();
                rsp.addHeader(entry.getKey(), value.substring(1, value.length()-1));
            });
            try (PrintWriter out = rsp.getWriter()) {
                out.write(JSON.toJSONString(exchange.getBody()));
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
        } else {
            logger.info("error: URL:" + "http://" + cloudIp + ":15120" + req.getRequestURI().substring(req.getContextPath().length()));
            try (PrintWriter out = rsp.getWriter()) {
                out.write("请求异常");
            } catch (Exception e1) {
                logger.error(e1.getMessage() + e1);
            }
        } 
    }
}

使用filter解决跨域

在web.xml配置拦截器

 <filter>
  <filter-name>servletFilterTest</filter-name>
  <filter-class>cn.test.intercepter.ServletFilterTest</filter-class>
 </filter>
 <filter-mapping>
  <filter-name>servletFilterTest</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>

过滤器代码

import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ServletFilterTest implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        httpServletRequest.getSession();
        HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
        httpResponse.setHeader("Access-Control-Allow-Origin", "*");
        httpResponse.setHeader("Access-Control-Allow-Methods", "*");
        httpResponse.setHeader("Access-Control-Max-Age", "3600");
        httpResponse.setHeader("Access-Control-Allow-Headers",
                "Origin, X-Requested-With, Content-Type, Accept, Connection, User-Agent, Cookie");
        httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
        httpResponse.setHeader("Content-type", "application/json");
        httpResponse.setHeader("Cache-Control", "no-cache, must-revalidate");
        if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
            return ;
        }
        filterChain.doFilter(httpServletRequest, httpResponse);
    }
    @Override
    public void destroy() {
    }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • java通过DelayQueue实现延时任务

    java通过DelayQueue实现延时任务

    本文主要介绍了java通过DelayQueue实现延时任务,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • java反射机制实战示例分享

    java反射机制实战示例分享

    这篇文章主要介绍了java反射机制实战示例,需要的朋友可以参考下
    2014-03-03
  • Java 中EasyExcel的使用方式

    Java 中EasyExcel的使用方式

    这篇文章主要介绍了Java 中EasyExcel的使用方式,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下
    2022-08-08
  • Java 判断字符串a和b是否互为旋转词

    Java 判断字符串a和b是否互为旋转词

    本篇文章主要介绍了判断字符串a和b是否互为旋转词的相关知识,具有很好的参考价值。下面跟着小编一起来看下吧
    2017-05-05
  • Springboot之日志、配置文件、接口数据如何脱敏

    Springboot之日志、配置文件、接口数据如何脱敏

    本文主要介绍了Springboot之配置文件数据脱敏、接口返回数据脱敏、日志文件数据脱敏三个方面,需要了解学习的小伙伴快跟随小编的脚步一起去看看吧
    2021-09-09
  • Spring Boot应用中如何动态指定数据库实现不同用户不同数据库的问题

    Spring Boot应用中如何动态指定数据库实现不同用户不同数据库的问题

    让我们创建一个 Spring Boot 项目首先设置一个具有必要依赖项的新 Spring Boot项目,在项目配置中包括 Spring Web、Spring Data JPA 和关于数据库的依赖项,接下来介绍Spring Boot应用中如何动态指定数据库,实现不同用户不同数据库的场景 ,需要的朋友可以参考下
    2024-04-04
  • Java设计模式中代理模式应用详解

    Java设计模式中代理模式应用详解

    代理模式(Proxy Parttern)为一个对象提供一个替身,来控制这个对象的访问,即通过代理对象来访问目标对象。本文将通过示例详细讲解一下这个模式,需要的可以参考一下
    2022-11-11
  • 前端RSA加密java后端解密示例代码

    前端RSA加密java后端解密示例代码

    这篇文章主要介绍了RSA非对称加密的原理,前端使用公钥加密数据,后端使用私钥解密,提供了前端和后端实现的示例代码,包括依赖、接口、工具类等,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-11-11
  • java中String StringBuffer和StringBuilder的区别详解

    java中String StringBuffer和StringBuilder的区别详解

    大家好,本篇文章主要讲的是java中String StringBuffer和StringBuilder的区别详解,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01
  • System.identityHashCode和hashCode的区别及说明

    System.identityHashCode和hashCode的区别及说明

    String调用hashCode()和System.identityHashCode()返回值不同是因为String重写了hashCode()方法,而System.identityHashCode()返回对象的内存地址哈希值;Test调用两个方法返回值相同是因为Test没有重写hashCode()方法,因此两者调用底层的JVM_IHashCode方法返回相同值
    2024-11-11

最新评论