zoukankan      html  css  js  c++  java
  • Spring boot + Shiro 在前后端分离时,ajax跨域问题(OPTIONS问题)

    # 一. 错误出现

    在前后端分离时,遇到前端请求后报跨域

    # 二. 排查原因

     后台已经进行过spring boot 的统一跨域处理。按理说不会出现这个问题,因为跨域是指一个用户从网站A访问网站B的资源,导致出现一个跨域请求,一般出现在前后端分离项目的页面访问接口的时候。可即使处理过,依旧存在这个问题。

    我的情况是,前端页面登录可用,其余接口无法使用,初步怀疑是shiro的问题。在确认前端headers 中包含正确的权限字符串后。我就写了个过滤器,查看请求具体情况。

    import javax.servlet.*;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class MyOptionsFilter implements Filter {
        @Override
        public void doFilter(ServletRequest req, ServletResponse resp,
                             FilterChain chain) throws IOException, ServletException {
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) resp;
            
        }
    }

    发现请求过来的请求不是 GET / POST 而是 OPTIONS !

    查阅文章后发现,这是ajax在设置header后发送请求,它会先发送OPTIONS请求,验证服务端是否可用,再发送GET / POST请求。即 请求两次!

    # 三 解决问题

    发现可能存在的问题后,在过滤器中对OPTIONS请求做处理即可

    import org.springframework.http.HttpStatus;
    
    import javax.servlet.*;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class MyOptionsFilter implements Filter {
        @Override
        public void doFilter(ServletRequest req, ServletResponse resp,
                             FilterChain chain) throws IOException, ServletException {
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) resp;
    
            response.setHeader("Access-control-Allow-Origin", request.getHeader("Origin"));
            response.setHeader("Access-Control-Allow-Credentials", "true"); //为true时 Origins设置为 * 可能会存在问题!
            response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));
            response.addHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
            if ("OPTIONS".equals(request.getMethod())) {
                response.setStatus(HttpStatus.NO_CONTENT.value());
                return;
            } else {
                chain.doFilter(request, response);
            }
        }
    }
    

      

    因为我使用的框架是spring boot 需要在shiro的config中配置过滤器,代码如下。

        @Bean
        public FilterRegistrationBean replaceTokenFilter(){
            FilterRegistrationBean registration = new FilterRegistrationBean();
            registration.setName("MyOptionsFilter");//spring 协助注入,注意名称不要重复
            registration.setFilter( new MyOptionsFilter());
            registration.setDispatcherTypes(DispatcherType.REQUEST); //拦截请求
            registration.addUrlPatterns("/*");//拦截请求url
            registration.setOrder(1);//排序第一,避免影响。
            return registration;
        }
    

      

    半水宥坐,中庸之道。
  • 相关阅读:
    C——联合体(共同体)总结
    JMX操作ActiveMQ(1)
    使用xml和java代码混合控制UI界面
    Hive Metastore ObjectStore PersistenceManager自动关闭bug解析
    (算法课大报告)大数据的查找与排序
    编程珠玑---读书笔记---使用后缀数组查找最长重复子串
    VMware vSphere服务器虚拟化实验十一高可用性之三Fault Tolerance
    签名应用例子
    fopen()惹的祸
    Bigcommerce: 给已完成购买的客户发送一封产品评论邮件,让客户直接进行产品评论
  • 原文地址:https://www.cnblogs.com/ShineAnthony/p/14124495.html
Copyright © 2011-2022 走看看