java跨域问题解决

问题描述:在使用前后端分离的情况下,前端访问后端时会出现跨域问题

解决方式:

1.设置跨域

1)、单个控制器方法CORS注解

在单个方法中加入注解@CrossOrigin。

2)、整个控制器启用CORS注解

在整个控制器上添加注解@CrossOrigin,其中origins为跨域的Url链接,maxAge为允许跨域的时间。

3)、全局CORS配置(在ResourcesConfig重写addCorsMappings方法)

2.获得跨域参数 

    原因:跨域时实际上发送了两次请求,第一次为OPTIONS请求,第二次才是实际的GET/POST请求

  • OPTIONS请求中,不会携带请求头的参数,所以在拦截器上获取的请求头为空,自定义拦截器拦截成功
  • 第一次求情不能通过,就无法获得第二次的请求了(例如get/post等)
  • 只有第二次的请求带参数

    解决:

        1.处理第一次的请求

在拦截器中,如果请求为OPTION,则直接忽略:

1 String method = request.getMethod();
2 //判断是否是OPTIONS请求,如果是则忽略
3 if(HttpMethod.OPTIONS.toString().equals(method)){
4     return true;  
5 }

       2.获取参数

1).addInterceptors拦截

WebMvcConfigurer中有addInterceptors拦截方法

@Configuration
public class WebMvcConfig implements WebMvcConfigurer{
    @Resource
    private VersionInterceptor versionInterceptor;
    @Resource
    private DeviceInterceptor deviceInterceptor;
    //自定义拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry){
        registry.addInterceptor(versionInterceptor).addPathPatterns("/**");
        registry.addInterceptor(deviceInterceptor).addPathPatterns("/**");
    }  

}

         实现DeviceInterceptor方法,获取参数

@Component
public class DeviceInterceptor implements HandlerInterceptor{
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
        //跳过请求为OPTION的请求
        String method = request.getMethod();
        //判断是否是OPTIONS请求
        if(HttpMethod.OPTIONS.toString().equals(method)){
            return true;
        }

        //以参数device为例
        String device = ServletUtil.getHeader(request, HeadConstant.DEVICE, CharsetUtil.UTF_8);
        if(StringUilts.isEmpty(device)){
            response.setContentType("application/json; charset=utf-8");
            response.getWriter().print(JSONUtil.toJsonStr("请求参数不正确"));
            return false;
        }
        return true;
    }
}    

  2)多滤器例子

//filterName:过滤器名字,   urlPatterns:拦截的url,/*是都拦截        
@WebFilter(filterName = "tokenFilter", urlPatterns = {"/*"})        
//注入容器,没有这个注解,过滤器无效        
@Component        
public class TokenFilter implements Filter {        
    /**        
     * 用于测试        
     */        
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss SSS");        
        
    @Override        
    public void init(FilterConfig config) throws ServletException {        
        log.info("过滤器TokenFilter初始化");        
    }        
        
        
    @Override        
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws ServletException, IOException {        
        HttpServletRequest request = (HttpServletRequest) servletRequest;        
        HttpServletResponse response = (HttpServletResponse) servletResponse;        
        
        
        // 响应标头指定 指定可以访问资源的URI路径        
        String origin = request.getHeader("Origin");        
        response.setHeader("Access-Control-Allow-Origin", origin);        
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");        
        response.setHeader("Access-Control-Max-Age", "3600");        
        //  设置  受支持请求标头(自定义  可以访问的请求头  例如:Token)        
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization,token,Origin,Content-Type,Accept");        
        // 指示的请求的响应是否可以暴露于该页面。当true值返回时它可以被暴露        
        response.setHeader("Access-Control-Allow-Credentials", "true");        
        
        /**        
         * 发送两次请求        
         * 第一次是 request.getMethod()=OPTIONS        
         * 第二次 request.getMethod()=GET/POST。。。        
         * 如果是OPTIONS请求则放行        
         */        
        if (HttpMethod.OPTIONS.toString().equals(request.getMethod())){        
            chain.doFilter(servletRequest, servletResponse);        
        }        
        
        System.out.println("-----------------------------------------------");        
        System.out.println("到达过滤器,时间:" + simpleDateFormat.format(new Date()));        
        System.out.println("请求头中的Authorization:" + request.getHeader("Authorization"));        
        System.out.println("请求URL:" + request.getRequestURL());        
        System.out.println("请求方式:" + request.getMethod());        
        
        chain.doFilter(servletRequest,servletResponse);        
    }        
        
    @Override        
    public void destroy() {        
        log.info("过滤器TokenFilter销毁");        
    }        
        
}        

 

posted @ 2022-12-17 13:53  摧残一生  阅读(2327)  评论(0编辑  收藏  举报