package interceptor; import annotation.ApiLogin; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import com.alibaba.druid.support.json.JSONUtils; import com.util.ThirdSessionHolder; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.shiro.authc.AuthenticationException; import org.jeecg.common.constant.CommonConstant; import org.jeecg.common.exception.JeecgBoot401Exception; import org.jeecg.common.exception.JeecgBootException; import org.jeecg.common.system.util.JwtUtil; import org.jeecg.common.util.RedisUtil; import org.jeecg.common.util.TenantContextHolder; import org.jeecg.modules.wxuser.entity.ThirdSession; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.concurrent.TimeUnit; /** * ThirdSession拦截器,校验每个请求的ThirdSession * @author */ @Slf4j //@AllArgsConstructor @Component public class ThirdSessionInterceptor implements HandlerInterceptor { //public class ThirdSessionInterceptor extends HandlerInterceptorAdapter { // private final RedisTemplate redisTemplate; @Resource private RedisUtil redisUtil; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // if (!(handler instanceof HandlerMethod)) { // return super.preHandle(request, response, handler); // } if ((handler instanceof HandlerMethod)) { HandlerMethod method = (HandlerMethod) handler; //判断访问的control是否添加ApiLogin注解 ApiLogin apiLogin = method.getMethodAnnotation(ApiLogin.class); String appIdHeader = request.getHeader("app-id"); //小程序端的所有接口需要登录才能访问,校验thirdSession return this.judeSession(request, response, apiLogin); } return Boolean.TRUE; } /** * 校验session * @param request * @param response * @return * @throws IOException */ private boolean judeSession(HttpServletRequest request, HttpServletResponse response, ApiLogin apiLogin) throws IOException { //获取header中的ThirdSession String thirdSessionHeader = request.getHeader("third-session"); if (StrUtil.isNotBlank(thirdSessionHeader)) { //获取缓存中的ThirdSession String key = CommonConstant.PREFIX_WX_APP_USER_TOKEN + thirdSessionHeader; Object thirdSessionObj = redisUtil.get(key); if (thirdSessionObj == null) {//session过期 ThirdSessionHolder.clear(); this.writerPrint(response, "登录超时,请重新登录"); return Boolean.FALSE; } else { String thirdSessionStr = String.valueOf(thirdSessionObj); ThirdSession thirdSession = JSONUtil.toBean(thirdSessionStr, ThirdSession.class); //判断session是否属于当前tenantId、appId String tenantIdHeader = request.getHeader("tenant-id"); if (StrUtil.isNotBlank(tenantIdHeader) && !thirdSession.getTenantId().equals(tenantIdHeader)) { this.writerPrint(response, "登录超时,请重新登录"); return Boolean.FALSE; } String appIdHeader = request.getHeader("app-id"); if (StrUtil.isNotBlank(appIdHeader) && StrUtil.isNotBlank(thirdSession.getAppId()) && !thirdSession.getAppId().equals(appIdHeader)) { this.writerPrint(response, "登录超时,请重新登录"); return Boolean.FALSE; } redisUtil.expire(key, JwtUtil.EXPIRE_TIME * 24 * 30 / 1000);//更新session过期时间 TenantContextHolder.setTenantId(thirdSession.getTenantId());//设置租户ID ThirdSessionHolder.setThirdSession(thirdSession);//设置thirdSession if (apiLogin != null && apiLogin.mustLogin()) { //此接口必须登录商城才能访问 return this.judeSessionUserMall(response, thirdSession); } return Boolean.TRUE; } } else { this.writerPrint(response, "session不能为空"); return Boolean.FALSE; } } /** * 校验session是否商城登录 * @param thirdSession * @return * @throws IOException */ private boolean judeSessionUserMall(HttpServletResponse response, ThirdSession thirdSession) throws IOException { String userId = thirdSession.getUserId(); if(StrUtil.isBlank(userId)){ this.writerPrint(response, "请先登录"); return Boolean.FALSE; } return Boolean.TRUE; } private void writerPrint(HttpServletResponse response, String msg) throws IOException { //返回401错误码,触发小程序重新登录 JwtUtil.responseError(response,401,msg); } }