美文网首页程序员代码改变世界
spring mvc跨域请求处理

spring mvc跨域请求处理

作者: 子龙爱弹琴 | 来源:发表于2017-04-08 17:15 被阅读678次

    我们现在开发的应用一般都会将前台和后台进行数据传输,或者是我们的应用服务器需要提供数据给多个应用使用的时候,要注意的是跨域是浏览器设置的一个安全策略,也就是说,要是我们的服务不是提供给浏览器使用的,就不需要考虑跨域的问题,当然要是我们进行的是web应用的开发的话,就要关注跨域的问题了

    浏览器对不同域名的请求的处理是,先发送一个options的请求,该请求只是单纯的将服务器的响应头和我们的请求头进行比较,如果响应头里面设置了允许跨域的话,就发送真正的数据请求过去

    servlet容器中对于options的请求默认是不会分发的我们的业务控制器层的,所以我们可以有两种方式来实现对于跨域请求的处理

    1. 使用filter

    filter是web容器层,也就是servlet容器对请求进行过滤,所以我们可以使用filter在servlet容器对options请求进行处理之前自己进行一番处理,首先我们需要实现servlet的filter接口,然后在里面对请求进行处理,如:

    package uc.meven.test2.filter;
    
    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletResponse;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    
    @Component
    public class MyCORSFilter implements Filter{
        
        private static final Logger log = LoggerFactory.getLogger(MyCORSFilter.class);
        
        @Override
        public void destroy() {
            // TODO Auto-generated method stub
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
                throws IOException, ServletException {
            HttpServletResponse response = (HttpServletResponse) servletResponse; 
            // String origin = (String) servletRequest.getRemoteHost()+":"+servletRequest.getRemotePort(); 
            response.setHeader("Access-Control-Allow-Origin", "*"); 
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); 
            response.setHeader("Access-Control-Max-Age", "3600"); 
            response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization,x-csrf-token");
            response.setHeader("Access-Control-Allow-Credentials","true"); 
            filterChain.doFilter(servletRequest, servletResponse);
        }
    
        @Override
        public void init(FilterConfig arg0) throws ServletException {
            // TODO Auto-generated method stub
        }
    
    }
    
    

    然后在web容器中加上我们自定义的过滤器,也就是在web.xml中

    <filter> 
        <filter-name>cors</filter-name>
        <!--定义的filter类的位置-->
        <filter-class>uc.meven.test2.filter.MyCORSFilter</filter-class>
    </filter>
    <filter-mapping>
        <!--只过滤一部分请求,/ajax下的全部请求都可以跨域-->
        <filter-name>cors</filter-name>
        <url-pattern>/ajax/*</url-pattern>
    </filter-mapping>
    
    1. 另外我们也可以不在servlet容器层对跨域请求进行处理,可以上浮到我们的spring层,这时我们需要将servlet对于options请求不进行分发的配置给开起来,在web.xml中加入
    <init-param>
      <param-name>dispatchOptionsRequest</param-name>
      <param-value>true</param-value>
    </init-param>
    

    然后我们可以加入一个interceptor的请求拦截器,对所有的请求进行拦截,设置允许跨域,这时我们需要实现spring的HandlerInterceptor拦截器接口,对options请求进行处理

    package uc.meven.test2.interceptor;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.http.HttpHeaders;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    public class AccessControllerInterceptor implements HandlerInterceptor {
        private static final Logger log = LoggerFactory.getLogger(AccessControllerInterceptor.class);
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            log.info("enter interceptor===========");
            // TODO Auto-generated method stub
            final String uri = request.getRequestURI();
            final String origin = request.getHeader(HttpHeaders.ORIGIN);
            response.setHeader("Access-Control-Allow-Origin", origin);
            response.setHeader("Access-Control-Allow-Credentials", "true");
            response.setHeader("Access-Control-Allow-Headers", "Content-Type, accept, apikey, sign, timestamp");
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
            log.info("request uri:{}, origin:{}, access success", uri, origin);
            // 如果是options请求的话,直接返回,不是的话到业务层进行处理
            return !"options".equalsIgnoreCase(request.getMethod());
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                ModelAndView modelAndView) throws Exception {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
                throws Exception {
            // TODO Auto-generated method stub
            
        }
    
    }
    
    

    接下来我们需要在springmvc的配置中启用我们的interceptor

    <mvc:interceptors>
        <bean class="uc.meven.test2.interceptor.AccessControllerInterceptor" />
    </mvc:interceptors>
    

    虽然我们可以使用第二中方式来实现跨越请求的处理,但是按照软件分层的概念,我们应该再servlet容器层进行这方面的处理,不污染我们的业务层代码,所以推荐使用第一种方式

    相关文章

      网友评论

        本文标题:spring mvc跨域请求处理

        本文链接:https://www.haomeiwen.com/subject/vcalattx.html