springboot|springboot 前后端分离解决跨域问题

【springboot|springboot 前后端分离解决跨域问题】1、程序入口加入servlet包扫描: @ServletComponentScan(basePackages = {"com.ada.common.security"})

@SpringBootApplication @MapperScan({"com.ada.dao"}) @ServletComponentScan(basePackages = {"com.ada.common.security"}) public class AdaApplication {public static void main(String[] args) { SpringApplication.run(AdaApplication.class, args); }}

2、在@ServletComponentScan指定目录下新增LoginFilter类实现Filter接口:
package com.ada.common.security; import com.ada.common.domain.security.FrmUser; import org.springframework.core.annotation.Order; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebFilter(urlPatterns = {"/*"}, filterName = "loginFilter") @Order(1) public class LoginFilter2 implements Filter {@Override public void init(FilterConfig filterConfig) throws ServletException {}/** * 支持跨域访问 * * @param req * @param rsp */ private void setHeader(HttpServletRequest req, HttpServletResponse rsp) { rsp.setHeader("Access-Control-Allow-Origin", req.getHeader("Origin")); rsp.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); rsp.setHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS,DELETE"); rsp.setHeader("Access-Control-Max-Age", "3600"); rsp.setHeader("Access-Control-Allow-Credentials", "true"); rsp.addCookie(new Cookie("JSSESIONID", req.getSession().getId())); }//允许匿名访问你的地址 private static final String[] anonUrls = {"/login", "/notLogin"}; //允许匿名访问的地址处理 private boolean anonURL(String url) { for (String anonUrl : anonUrls) { if (url.indexOf(anonUrl) != -1) { return true; } } return false; }@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) servletRequest; HttpServletResponse rsp = (HttpServletResponse) servletResponse; this.setHeader(req, rsp); //支持跨域请求//匿名访问处理 if (anonURL(req.getRequestURI())) { filterChain.doFilter(req, rsp); return; }//从session中或者从redis缓存中获取用户、权限等信息进行校验,按照自己项目实际情况进行处理即可 FrmUser user = (FrmUser) req.getSession().getAttribute("user"); if (user == null) { //1、这里注意要使用request的请求转发; //2、不要使用response的重定向或者print方法,使用重定向会导致跨域设置失效,知道如何处理的大神欢迎提供解决方案 //3、转发地址可以设置为返回JSON的controller接口,这样就实现了返回指定格式的JOSN给前端了 req.getRequestDispatcher("/notLogin").forward(req, rsp); } else { filterChain.doFilter(req, rsp); }}@Override public void destroy() {} }

3、到此服务端处理就完成了
4、关于前端的问题,服务端使用sessionid时,在跨域请求时,一定要在请求中加入:withCredentials: true;否则每次请求的sessionid都是不一样的,以angular为例:
intercept(req: HttpRequest, next: HttpHandler): Observable { const authReq = req.clone({ setHeaders: { 'Content-Type': 'application/json; charset=UTF-8', }, withCredentials: true //防止每次跨域请求时sessionid不一致的问题 }); return next.handle(authReq).pipe( retry(2), // retry a failed request up to 2 times catchError(err => { return this.handleError(err); }) ) }


    推荐阅读