彻底解决SSM项目前后端分离带来的跨域问题
说明
总结了一下SSM中解决跨域的几种方式。如果项目是用SpringBoot构建的,则有更加优雅的解决方式:https://www.cnblogs.com/phdeblog/p/13260784.html
当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。对应到当前场景就是,项目前后端分离,不管是开发阶段,还是最后部署,前后端代码都不在一个服务器上。
如果前后台是通过session进行身份认证,那么前端每次访问后台的时候,都会携带一个cookie,比如ajax(axios也一样)发起请求时设置
xhrFields:{ withCredentials:true },
这个时候如果后台仅仅设置
response.setHeader("Access-Control-Allow-Origin", "*");
是没有效果的,依然存在跨域问题。如果前端携带cookie,后台必须指定详细的ip,例如把“*”换成“http://localhost:8081”。
知道这一点后,就可以根据不同的业务场景,来编写合适的过滤器了。
版本一:简易版
适用于开发阶段,不需要记录用户状态、前端没有携带cookie时,则可以这么做:
过滤器
public class SimpleCorsFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); response.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token"); response.setHeader("Access-Control-Max-Age", "0"); filterChain.doFilter(servletRequest, servletResponse); } }
如果前端携带cookie,可以把 response.setHeader("Access-Control-Allow-Origin", "*");中的*换成具体的ip+端口, 例如:http://127.0.0.1:8080
配置web.xml
<filter> <filter-name>SimpleCorsFilter</filter-name> <filter-class>czams.front.filter.SimpleCorsFilter</filter-class> </filter> <filter-mapping> <filter-name>SimpleCorsFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
版本二:选择是否开启跨域
在上面的基础上,经过如下改造后,可在web.xml选择是否开启跨域
过滤器
public class SimpleCorsFilter implements Filter { private boolean isCross = false; private final List<String>allowedOrigin = Arrays.asList("http://192.168.1.202:5500","http://127.0.0.1:5500"); @Override public void destroy() { isCross = false; } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { if(isCross){ HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; String origin = request.getHeader("Origin"); response.setHeader("Access-Control-Allow-Origin", allowedOrigin.contains(origin) ?origin:""); response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); response.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token"); response.setHeader("Access-Control-Max-Age", "0"); response.setHeader("Access-Control-Allow-Credentials" , "true"); filterChain.doFilter(servletRequest, servletResponse); } } @Override public void init(FilterConfig filterConfig) throws ServletException { String isCrossStr = filterConfig.getInitParameter("isCross"); isCross = isCrossStr.equals("true"); }
}
在Arrays.asList()方法里配置ip。
web.xml
<filter> <filter-name>SimpleCorsFilter</filter-name> <filter-class>czams.front.filter.SimpleCorsFilter</filter-class> <init-param> <param-name>isCross</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>SimpleCorsFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
通过配置web.xml中的isCross变量选择是否开启跨域。
版本三:在web.xml中配置ip地址
如果觉得在代码里改ip太麻烦了,也可以选择从配置文件中读取
过滤器
public class SimpleCorsFilter implements Filter { private boolean isCross = false; private List<String>allowedOrigin = null; @Override public void destroy() { isCross = false; } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; String origin = request.getHeader("Origin"); response.setHeader("Access-Control-Allow-Origin", allowedOrigin.contains(origin) ?origin:""); response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); response.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token"); response.setHeader("Access-Control-Max-Age", "0"); response.setHeader("Access-Control-Allow-Credentials" , "true"); filterChain.doFilter(servletRequest, servletResponse); } @Override public void init(FilterConfig filterConfig) throws ServletException { String isCrossStr = filterConfig.getInitParameter("isCross"); isCross = isCrossStr.equals("true"); String origin = filterConfig.getInitParameter("origin"); String[] split = origin.split(","); allowedOrigin = Arrays.asList(split); } }
web.xml
注意逗号隔开,不加引号
<filter> <filter-name>SimpleCorsFilter</filter-name> <filter-class>czams.front.filter.SimpleCorsFilter</filter-class> <init-param> <param-name>isCross</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>origin</param-name> <param-value>http://127.0.0.1:5500,http://192.168.1.202:5500,http://localhost:5500</param-value> </init-param> </filter> <filter-mapping> <filter-name>SimpleCorsFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
其他
如果不想自己写,也可以导一下别人的包,配置一下过滤器即可
添加依赖
<dependency> <groupId>com.thetransactioncompany</groupId> <artifactId>cors-filter</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>com.thetransactioncompany</groupId> <artifactId>java-property-utils</artifactId> <version>1.10</version> </dependency>
web.xml
<filter> <filter-name>CORS</filter-name> <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class> <init-param> <param-name>cors.allowOrigin</param-name> <param-value>*</param-value> </init-param> <init-param> <param-name>cors.supportedMethods</param-name> <param-value>GET, POST, HEAD, PUT, DELETE</param-value> </init-param> <init-param> <param-name>cors.supportedHeaders</param-name> <param-value>Accept, Origin, X-Requested-With, Content-Type, Last-Modified</param-value> </init-param> <init-param> <param-name>cors.exposedHeaders</param-name> <param-value>Set-Cookie</param-value> </init-param> <init-param> <param-name>cors.supportsCredentials</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>CORS</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
参数也可以根据个人需要进行适当修改。