什么是跨域?
浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域
原因:
由于浏览器的同源策略, 即a网站只能访问a网站的内容,不能访问b网站的内容.
注意:
跨域问题只存在于浏览器,也就是说当你的前端页面访问后端简单请求的接口时,返回值是有的,只是服务器没有在请求头指定跨域的信息,所以浏览器自动把返回值给"屏蔽了".
经过上面的了解,可以得出几个解决跨域的方法(不考虑前端实现):
1.服务端指定跨域信息
2.在web页面与服务器之间加一层服务指定跨域信息,比如nginx
使用springboot提供了跨域的方法:
1.5版本为继承WebMvcConfigurerAdapter 类实现抽象方法,
//springboot 1.5方式
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedHeaders("*")
.allowedMethods("*")
.allowedOrigins("*")
.allowCredentials(true);
}
}
2.0以后为实现WebMvcConfigurer 接口重写方法
//springboot 2.0以上的方式
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedHeaders("Content-Type","X-Requested-With","accept,Origin","Access-Control-Request-Method","Access-Control-Request-Headers","token")
.allowedMethods("*")
.allowedOrigins("*")
.allowCredentials(true);
}
}
使用拦截器实现跨域:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new HandlerInterceptor() {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
response.addHeader("Access-Control-Allow-Headers",
"Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,token");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
});
}
}
注意:
请求头中自定义的字段是不允许跨域的,所以要指定
response.addHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,token");
或者
response.addHeader("Access-Control-Allow-Headers", "*");
还可以使用servlet提供的过滤器进行跨域配置:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* 请求的基本过滤器 预处理请求头
*/
@Component
@WebFilter(urlPatterns = {"/*"}, filterName = "tokenAuthorFilter")
public class TokenAuthorFilter implements Filter {
private static Logger LOG = LoggerFactory.getLogger(TokenAuthorFilter.class);
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse rep = (HttpServletResponse) response;
HttpSession session = req.getSession();
LOG.info("sessionId:{}", session.getId());
//LOG.info("Origin:{}", req.getHeader("Origin"));
//设置允许跨域的配置
// 这里填写你允许进行跨域的主机ip(正式上线时可以动态配置具体允许的域名和IP)
rep.setHeader("Access-Control-Allow-Origin", "*");
//rep.setHeader("Access-Control-Allow-Origin", "*");
rep.setHeader("Access-Control-Expose-Headers", jwtProperties.getHeader());
// 允许的访问方法
rep.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, PATCH");
// Access-Control-Max-Age 用于 CORS 相关配置的缓存
rep.setHeader("Access-Control-Max-Age", "3600");
rep.setHeader("Access-Control-Allow-Headers", "token, Origin, X-Requested-With, Content-Type, Accept");
//若要返回cookie、携带seesion等信息则将此项设置我true
rep.setHeader("Access-Control-Allow-Credentials", "true");
// 把获取的Session返回个前端Cookie
//rep.addCookie(new Cookie("JSSESIONID", session.getId()));
chain.doFilter(req, rep);
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
}
灵活的跨域方式:
如果我们只想提供一个方法可以跨域,那么可以使用注解的形式:
@CrossOrigin
@RestController
public class TestController {
}