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<any>, next: HttpHandler): Observable<HttpEvent<any>> {
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);
})
)
}