package com.sunyard.chsm.auth; import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; import com.sunyard.chsm.mapper.CryptoServiceApiMapper; import com.sunyard.chsm.model.R; import com.sunyard.chsm.model.entity.CryptoServiceApi; import com.sunyard.chsm.utils.JsonUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; import org.springframework.util.ObjectUtils; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.time.Duration; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; import static com.sunyard.chsm.constant.SecurityConstant.ATTRIBUTE_APP_USER; /** * @author liulu * @since 2024/11/13 */ @Slf4j @Component public class AuthHandler implements HandlerInterceptor, InitializingBean { private Cache>> cache = null; /** * token 过期时间, 分钟 */ @Value("${chsm.token.expireTime:720}") private Integer tokenExpireTime; @Resource private CryptoServiceApiMapper cryptoServiceApiMapper; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (!(handler instanceof HandlerMethod)) { return true; } AppUser user = (AppUser) request.getAttribute(ATTRIBUTE_APP_USER); if (Objects.isNull(user)) { return true; } HandlerMethod handlerMethod = (HandlerMethod) handler; AuthCode authCode = handlerMethod.getMethodAnnotation(AuthCode.class); if (authCode == null || ObjectUtils.isEmpty(authCode.value())) { request.setAttribute("used_service_ids", user.getServiceIds()); return true; } String code = authCode.value(); Map> codeServiceMap = cache.get(user.getTokenId(), k -> { List apis = cryptoServiceApiMapper.selectByServiceIds(user.getServiceIds()); return apis.stream().collect(Collectors.groupingBy(CryptoServiceApi::getApiCode, Collectors.mapping(CryptoServiceApi::getCryptoServiceId, Collectors.toList()))); }); if (codeServiceMap == null || !codeServiceMap.containsKey(code)) { log.warn("app: {}-{}, 无权访问: {} - {}", user.getAppId(), user.getName(), code, request.getRequestURI()); response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.getOutputStream().write(JsonUtils.toJsonBytes(R.error("无权访问: " + request.getRequestURI()))); return false; } request.setAttribute("used_service_ids", codeServiceMap.get(code)); return true; } @Override public void afterPropertiesSet() throws Exception { cache = Caffeine.newBuilder() .expireAfterWrite(Duration.ofMinutes(tokenExpireTime)) .maximumSize(400L) .build(); } }