跨域--CORS

+++++++++++++++CORS与JSONP的使用目的相同,但是比JSONP更强大。+++++++++++++++
++++++++++++++JSONP只支持GET请求,CORS支持所有类型的HTTP请求。++++++++++++++
+++++++JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。+++++++

        简介: CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能。整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨域,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。 浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
       
           header里面有自定义的参数。都属于非简单请求---预检请求和正式请求:此文章忽略简单请求的功能说明。非简单请求的CORS请求,比如:POST/PUT/DETELE,会在正式发出请求之前,增加一次HTTP查询请求,称为"预检"请求(preflight),采OPTION的请求方式。 预检请求是浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。
           服务器正确回应的CORS相关字段如下(取决于服务端的设置):
  Access-Control-Allow-Methods: GET, POST, PUT
  Access-Control-Allow-Headers: X-Custom-Header
  Access-Control-Allow-Credentials: true
  Access-Control-Max-Age: 1728000

(1)Access-Control-Allow-Methods
该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。

(2)Access-Control-Allow-Headers
如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段。

(3)Access-Control-Allow-Credentials
该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。

(4)Access-Control-Max-Age
该字段可选,用来指定本次预检请求的有效期,单位为秒。上面结果中,有效期是20天(1728000秒),即允许缓存该条回应1728000秒(即20天),在此期间,不用发出另一条预检请求。

一:创建预检文件CrosFilter
    

public class CrosFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        if (request.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(request.getMethod())) {
            response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
            response.setHeader("Access-Control-Allow-Credentials", "true");
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
            response.setHeader("Access-Control-Max-Age", "3600");
            response.setHeader("Access-Control-Allow-Headers", "Content-Type,Accept,X-Requested-With,remember-me,accessToken");
        }
        filterChain.doFilter(request, response);
    }
}

二:web.xml
     
<filter>
    <filter-name>cors</filter-name>
    <filter-class>com.fqgj.youjie.agency.rest.filter.CrosFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>cors</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

三:UserAccessRightInterceptor

@Component
public class UserAccessRightInterceptor implements HandlerInterceptor {

    @Autowired
    private AdminService adminService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type,Accept,X-Requested-With,remember-me,bid,accessToken");

        String accessToken = request.getHeader("accessToken");

        if (StringUtils.isNotEmpty(accessToken)) {
            if (!hasPermission(accessToken)) {
                throw new ApplicationException("无效的token");
            }
        } else {
            HandlerMethod handlerMethod = (HandlerMethod) o;
            VisitorAccessible annotation = handlerMethod.getMethodAnnotation(VisitorAccessible.class);
            if (annotation != null) {
                return true;
            }

            if (!request.getMethod().equals("OPTIONS")) {
                if (!handlerMethod.getMethod().getName().toUpperCase().equals("LOGIN")) {
                    throw new ApplicationException("需要登陆才能访问");
                }
            }
        }

        return true;
    }


猜你喜欢

转载自blog.csdn.net/watson1360884839/article/details/79263486
今日推荐