|
|
|
@ -27,26 +27,43 @@ import static org.springframework.cloud.netflix.zuul.filters.support.FilterConst
|
|
|
|
* @Date 2019/1/3 10:21
|
|
|
|
* @Date 2019/1/3 10:21
|
|
|
|
* @CONTACT 317758022@qq.com
|
|
|
|
* @CONTACT 317758022@qq.com
|
|
|
|
* @DESC 关于后台管理系统,登陆不需要拦截,对于需要认证的富文本上传,需要特定的格式,所以,这里先对富文本放开,到controller里面进行特别处理
|
|
|
|
* @DESC 关于后台管理系统,登陆不需要拦截,对于需要认证的富文本上传,需要特定的格式,所以,这里先对富文本放开,到controller里面进行特别处理
|
|
|
|
* 前台,就不再在这里进行处理了,因为前台需要防止用户同级的攻击,所以需要userID,放到这里,controller那边不好处理
|
|
|
|
* 前台,就不再在这里进行处理了,因为前台需要防止用户同级的攻击,所以需要userID,放到这里,controller那边不好处理
|
|
|
|
|
|
|
|
* 该类是一个ZuulFilter的实现类,用于在Zuul网关中对请求进行过滤处理,主要针对后台管理系统的请求进行权限校验等相关操作,
|
|
|
|
|
|
|
|
* 根据不同的请求路径和用户身份等情况决定是否放行请求,或者返回相应的错误提示信息。
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
@Slf4j
|
|
|
|
@Slf4j
|
|
|
|
@Component
|
|
|
|
@Component
|
|
|
|
public class AdminUserFilter extends ZuulFilter {
|
|
|
|
public class AdminUserFilter extends ZuulFilter {
|
|
|
|
|
|
|
|
// 通过依赖注入获取CommonCacheUtil实例,用于后续从缓存(Redis)中获取用户相关信息
|
|
|
|
@Autowired
|
|
|
|
@Autowired
|
|
|
|
private CommonCacheUtil commonCacheUtil;
|
|
|
|
private CommonCacheUtil commonCacheUtil;
|
|
|
|
|
|
|
|
// 通过依赖注入获取Parameters实例,该实例可能包含了一些系统配置参数,比如不需要安全校验的路径等信息
|
|
|
|
@Autowired
|
|
|
|
@Autowired
|
|
|
|
private Parameters parameters;
|
|
|
|
private Parameters parameters;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 该方法用于指定过滤器的类型,返回值表明该过滤器属于前置过滤器(在请求路由之前执行),
|
|
|
|
|
|
|
|
* 对应的值取自Spring Cloud Zuul定义的常量PRE_TYPE,表示在请求被路由之前进行相关处理。
|
|
|
|
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public String filterType() {
|
|
|
|
public String filterType() {
|
|
|
|
return PRE_TYPE;
|
|
|
|
return PRE_TYPE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 该方法用于指定过滤器的执行顺序,返回值表示该过滤器在前置过滤器中的执行顺序,
|
|
|
|
|
|
|
|
* 通过取PRE_DECORATION_FILTER_ORDER减1的值来确定其相对顺序,使得该过滤器能在特定的顺序下执行,先于某些其他前置过滤器操作。
|
|
|
|
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public int filterOrder() {
|
|
|
|
public int filterOrder() {
|
|
|
|
return PRE_DECORATION_FILTER_ORDER-1;
|
|
|
|
return PRE_DECORATION_FILTER_ORDER - 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 该方法用于判断当前请求是否需要经过该过滤器进行处理,根据请求的URL等条件来决定。
|
|
|
|
|
|
|
|
* 首先获取当前请求的上下文以及对应的HttpServletRequest对象,然后获取请求的URL,
|
|
|
|
|
|
|
|
* 根据URL的内容判断是否需要进行权限校验,如果不符合校验条件则直接返回false表示不需要该过滤器处理,否则返回true。
|
|
|
|
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public boolean shouldFilter() {
|
|
|
|
public boolean shouldFilter() {
|
|
|
|
RequestContext requestContext = RequestContext.getCurrentContext();
|
|
|
|
RequestContext requestContext = RequestContext.getCurrentContext();
|
|
|
|
@ -54,63 +71,68 @@ public class AdminUserFilter extends ZuulFilter {
|
|
|
|
//获取当前请求的url
|
|
|
|
//获取当前请求的url
|
|
|
|
String url = request.getRequestURI();
|
|
|
|
String url = request.getRequestURI();
|
|
|
|
//前端的路径不在这里校验,直接放过
|
|
|
|
//前端的路径不在这里校验,直接放过
|
|
|
|
if (!url.contains("manage")){
|
|
|
|
if (!url.contains("manage")) {
|
|
|
|
log.info("【{}不需要进行权限校验】",url);
|
|
|
|
log.info("【{}不需要进行权限校验】", url);
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(url.contains("upload")){
|
|
|
|
if (url.contains("upload")) {
|
|
|
|
log.info("【{}不需要进行权限校验】",url);
|
|
|
|
log.info("【{}不需要进行权限校验】", url);
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//从配置文件获取所有门户需要校验的路径
|
|
|
|
//从配置文件获取所有门户需要校验的路径
|
|
|
|
// String[] passUrls = parameters.getNoneSecurityAdminPaths().toArray(new String[parameters.getNoneSecurityAdminPaths().size()]);
|
|
|
|
// String[] passUrls = parameters.getNoneSecurityAdminPaths().toArray(new String[parameters.getNoneSecurityAdminPaths().size()]);
|
|
|
|
// for(String str:passUrls){
|
|
|
|
// for (String str : passUrls) {
|
|
|
|
// //指定的路径比较特殊,也不在这里校验
|
|
|
|
// //指定的路径比较特殊,也不在这里校验
|
|
|
|
// if(url.contains("manage") && url.contains(str)){
|
|
|
|
// if (url.contains("manage") && url.contains(str)) {
|
|
|
|
// log.info("【{}不需要进行权限校验】",url);
|
|
|
|
// log.info("【{}不需要进行权限校验】", url);
|
|
|
|
// return false;
|
|
|
|
// return false;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
log.info("【{}----需要进行权限校验,必须是管理员身份才可以进入】",url);
|
|
|
|
log.info("【{}----需要进行权限校验,必须是管理员身份才可以进入】", url);
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 该方法是过滤器的核心执行逻辑所在,当shouldFilter方法返回true时会执行该方法,
|
|
|
|
|
|
|
|
* 在这里主要进行用户登录状态以及管理员权限的校验等操作,如果校验不通过则进行相应的错误处理,
|
|
|
|
|
|
|
|
* 如阻止请求路由、设置错误响应状态码、返回错误提示信息等,若校验通过则允许请求继续路由转发。
|
|
|
|
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public ServerResponse run() throws ZuulException {
|
|
|
|
public ServerResponse run() throws ZuulException {
|
|
|
|
RequestContext requestContext = RequestContext.getCurrentContext();
|
|
|
|
RequestContext requestContext = RequestContext.getCurrentContext();
|
|
|
|
HttpServletRequest request = requestContext.getRequest();
|
|
|
|
HttpServletRequest request = requestContext.getRequest();
|
|
|
|
//校验是否为管理员身份
|
|
|
|
//校验是否为管理员身份
|
|
|
|
String loginToken = CookieUtil.readLoginToken(request);
|
|
|
|
String loginToken = CookieUtil.readLoginToken(request);
|
|
|
|
log.info("【获取cookie----{}】",loginToken);
|
|
|
|
log.info("【获取cookie----{}】", loginToken);
|
|
|
|
if(StringUtils.isEmpty(loginToken)){
|
|
|
|
if (StringUtils.isEmpty(loginToken)) {
|
|
|
|
// // 过滤该请求,不对其进行路由
|
|
|
|
// // 过滤该请求,不对其进行路由
|
|
|
|
// requestContext.setSendZuulResponse(false);
|
|
|
|
// requestContext.setSendZuulResponse(false);
|
|
|
|
// //返回错误代码
|
|
|
|
// //返回错误代码
|
|
|
|
// requestContext.setResponseStatusCode(Constants.RESP_STATUS_NOAUTH);
|
|
|
|
// requestContext.setResponseStatusCode(Constants.RESP_STATUS_NOAUTH);
|
|
|
|
// return ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(),"用户未登录,无法获取当前用户信息");
|
|
|
|
// return ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(),"用户未登录,无法获取当前用户信息");
|
|
|
|
this.returnMsg(requestContext);
|
|
|
|
this.returnMsg(requestContext);
|
|
|
|
return ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(),"用户未登录,无法获取当前用户信息");
|
|
|
|
return ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(), "用户未登录,无法获取当前用户信息");
|
|
|
|
//throw new SnailmallException("用户未登录,无法获取当前用户信息");
|
|
|
|
//throw new SnailmallException("用户未登录,无法获取当前用户信息");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//2.从redis中获取用户信息
|
|
|
|
//2.从redis中获取用户信息
|
|
|
|
String userStr = commonCacheUtil.getCacheValue(loginToken);
|
|
|
|
String userStr = commonCacheUtil.getCacheValue(loginToken);
|
|
|
|
log.info("【从redis中获取用户信息:{}】",userStr);
|
|
|
|
log.info("【从redis中获取用户信息:{}】", userStr);
|
|
|
|
if(userStr == null){
|
|
|
|
if (userStr == null) {
|
|
|
|
// // 过滤该请求,不对其进行路由
|
|
|
|
// // 过滤该请求,不对其进行路由
|
|
|
|
// requestContext.setSendZuulResponse(false);
|
|
|
|
// requestContext.setSendZuulResponse(false);
|
|
|
|
// //返回错误代码
|
|
|
|
// //返回错误代码
|
|
|
|
// requestContext.setResponseStatusCode(Constants.RESP_STATUS_NOAUTH);
|
|
|
|
// requestContext.setResponseStatusCode(Constants.RESP_STATUS_NOAUTH);
|
|
|
|
// return ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(),"用户未登录,无法获取当前用户信息"); //SnailmallException(ResponseEnum.NEED_LOGIN.getCode(),"用户未登录,无法获取当前用户信息");
|
|
|
|
// return ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(),"用户未登录,无法获取当前用户信息"); //SnailmallException(ResponseEnum.NEED_LOGIN.getCode(),"用户未登录,无法获取当前用户信息");
|
|
|
|
this.returnMsg(requestContext);
|
|
|
|
this.returnMsg(requestContext);
|
|
|
|
return ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(),"用户未登录,无法获取当前用户信息");
|
|
|
|
return ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(), "用户未登录,无法获取当前用户信息");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
String url = request.getRequestURI();
|
|
|
|
String url = request.getRequestURI();
|
|
|
|
log.info("【获取当前url:{}】",url);
|
|
|
|
log.info("【获取当前url:{}】", url);
|
|
|
|
if(url.contains("manage")){
|
|
|
|
if (url.contains("manage")) {
|
|
|
|
log.info("【来到了管理后台,需要校验权限】");
|
|
|
|
log.info("【来到了管理后台,需要校验权限】");
|
|
|
|
User currentUser = JsonUtil.Str2Obj(userStr,User.class);
|
|
|
|
User currentUser = JsonUtil.Str2Obj(userStr, User.class);
|
|
|
|
log.info("【当前登陆的用户为:{}】",currentUser);
|
|
|
|
log.info("【当前登陆的用户为:{}】", currentUser);
|
|
|
|
if(!currentUser.getRole().equals(Constants.Role.ROLE_ADMIN)){
|
|
|
|
if (!currentUser.getRole().equals(Constants.Role.ROLE_ADMIN)) {
|
|
|
|
//不是管理员报错
|
|
|
|
//不是管理员报错
|
|
|
|
log.error("【当前登陆用户不是管理员身份】");
|
|
|
|
log.error("【当前登陆用户不是管理员身份】");
|
|
|
|
// 过滤该请求,不对其进行路由
|
|
|
|
// 过滤该请求,不对其进行路由
|
|
|
|
@ -119,7 +141,7 @@ public class AdminUserFilter extends ZuulFilter {
|
|
|
|
// requestContext.setResponseStatusCode(Constants.RESP_STATUS_NOAUTH);
|
|
|
|
// requestContext.setResponseStatusCode(Constants.RESP_STATUS_NOAUTH);
|
|
|
|
// return ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(),"用户未登录,无法获取当前用户信息");
|
|
|
|
// return ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(),"用户未登录,无法获取当前用户信息");
|
|
|
|
this.returnMsg(requestContext);
|
|
|
|
this.returnMsg(requestContext);
|
|
|
|
return ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(),"用户未登录,无法获取当前用户信息");
|
|
|
|
return ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(), "用户未登录,无法获取当前用户信息");
|
|
|
|
//throw new SnailmallException("用户权限不够");
|
|
|
|
//throw new SnailmallException("用户权限不够");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -127,10 +149,14 @@ public class AdminUserFilter extends ZuulFilter {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//返回没权限消息
|
|
|
|
//返回没权限消息
|
|
|
|
private void returnMsg(RequestContext ctx){
|
|
|
|
private void returnMsg(RequestContext ctx) {
|
|
|
|
|
|
|
|
// 设置响应的内容类型为JSON格式,字符编码为utf-8,确保返回的错误信息能被正确解析
|
|
|
|
ctx.getResponse().setContentType("application/json; charset=utf-8");
|
|
|
|
ctx.getResponse().setContentType("application/json; charset=utf-8");
|
|
|
|
ctx.setSendZuulResponse(false); //令zuul过滤该请求,不对其进行路由
|
|
|
|
// 令zuul过滤该请求,不对其进行路由,即阻止请求继续往后端服务转发
|
|
|
|
|
|
|
|
ctx.setSendZuulResponse(false);
|
|
|
|
|
|
|
|
// 设置响应的状态码,这里设置为Constants.RESP_STATUS_OK,可能需要根据实际情况确认是否合适(一般权限相关错误可以考虑用对应的错误状态码)
|
|
|
|
ctx.setResponseStatusCode(Constants.RESP_STATUS_OK);
|
|
|
|
ctx.setResponseStatusCode(Constants.RESP_STATUS_OK);
|
|
|
|
ctx.setResponseBody(JsonUtil.obj2String(ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(),"用户未登录,无法获取当前用户信息")));
|
|
|
|
// 将错误提示信息转换为JSON字符串,并设置为响应体的内容,以便客户端能获取到具体的错误提示信息
|
|
|
|
|
|
|
|
ctx.setResponseBody(JsonUtil.obj2String(ServerResponse.createByErrorCodeMessage(ResponseEnum.NEED_LOGIN.getCode(), "用户未登录,无法获取当前用户信息")));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|