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);
      })
    )
  }

 

你可能感兴趣的:(springboot,Java)