在vue-element-admin登录集成时候碰到跨域资源共享问题,CORS(Cross-origin resource sharing)是浏览器的技术规范,浏览器可以发起跨域请求但Javascript脚本不能,传统的ajax只能获取在同域名下的资源,但Html5允许ajax发起跨域请求,解决方案有:JSONP、Flash、IFrame、CORS。
一、CORS(跨域资源共享)问题
针对vue-element-admin的登录模块的后端接口完成后,前端调用时候出现报错,因为前端的端口是9527而后端的端口是9090,端口不同,浏览器就认为调用的接口出现跨域请求问题(跨域是浏览器问题,浏览器可以关掉该机制),
Access to XMLHttpRequest at 'http://localhost:9090/user/login' from origin 'http://localhost:9527' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. [http://localhost:9527/#/login?redirect=%2Fdashboard]
二、后端解决CORS问题
两种常用解决方法,都是通过配置类方式进行,一种是原生的java.servlet类;
package com.example.testspring.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter(filterName = "CORSFilter", urlPatterns = {"/*"})
@Order(value = 1)
@Configuration
public class CorsFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)throws IOException, ServletException {
System.out.println("Filter 过滤器 执行 了");
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
// 响应标头指定 指定可以访问资源的URI路径
response.setHeader("Access-Control-Allow-Origin", "*");
//响应标头指定响应访问所述资源到时允许的一种或多种方法
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
//设置 缓存可以生存的最大秒数
response.setHeader("Access-Control-Max-Age", "3600");
//设置 受支持请求标头
response.setHeader("Access-Control-Allow-Headers", "*");
// 指示的请求的响应是否可以暴露于该页面。当true值返回时它可以被暴露
response.setHeader("Access-Control-Allow-Credentials","true");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {}
}
另一种是通过springMVC的注释类:
package com.example.testspring.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.filter.CorsFilter;
@Slf4j
@Configuration
public class CorsConfiguration implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
log.info("===CORS已注入===");
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "DELETE", "PUT","OPTION","OPTIONS")
.allowedHeaders("x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN,token,username,client")
.exposedHeaders("x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN,token,username,client")
.maxAge(18000);
}
}
如果后端自定义了拦截器,需要增加对预检请求的处理;
// 预检请求,预检飞行
if(CorsUtils.isCorsRequest(request) && "OPTIONS".equals(request.getMethod())){
response.setCharacterEncoding( "UTF-8");
response.setContentType( "application/json; charset=utf-8");
response.setStatus(200);
response.setHeader("Access-Control-Allow-Credentials","true");
response.setHeader("Access-Control-Allow-Origin","http://localhost:9527");
response.setHeader("Access-Control-Allow-Origin","https://www.tiny.cloud/");
response.setHeader("Access-Control-Allow-Headers","x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN,token,username,client");
response.setHeader("Access-Control-Expose-Headers","x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN,token,username,client");
PrintWriter out = null ;
try{
JSONObject res = new JSONObject();
res.put( "200", "sucess");
out = response.getWriter();
out.append(res.toString());
return false;
}
catch (Exception e){
e.printStackTrace();
response.sendError( 500);
return false;
}