shz.spring.api.AbstractApiInterceptor Maven / Gradle / Ivy
package shz.spring.api;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import shz.core.msg.ClientFailure;
import shz.core.msg.ClientFailureMsg;
import shz.core.msg.ServerFailureMsg;
import shz.core.net.api.ApiMethodAndPath;
import shz.spring.auth.AuthService;
import shz.spring.session.Session;
import shz.spring.session.SessionHolder;
import shz.spring.token.TokenIdentity;
import shz.spring.token.TokenInfo;
import shz.spring.token.TokenService;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public abstract class AbstractApiInterceptor implements HandlerInterceptor, WebMvcConfigurer {
protected final String appName;
protected final AuthService authService;
protected final TokenService tokenService;
protected AbstractApiInterceptor(String appName, AuthService authService, TokenService tokenService) {
this.appName = appName;
this.authService = authService;
this.tokenService = tokenService;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(this);
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if (!(handler instanceof HandlerMethod)) return true;
HandlerMethod handlerMethod = (HandlerMethod) handler;
ApiMethodAndPath methodAndPath = ApiMethodAndPathGetter.get(handlerMethod.getBeanType(), handlerMethod.getMethod());
ClientFailure.BAD_METHOD.requireNonNull(methodAndPath);
String method = methodAndPath.getMethod();
String path = methodAndPath.getPath();
if (ignore(appName, method, path)) return true;
//获取当前会话
Session session = SessionHolder.getNonNull(request);
ApiDetail apiDetail = getApiDetail(appName, method, path);
ServerFailureMsg.requireNonNull(apiDetail, "缺失API[appName:%s,method:%s,path:%s]", appName, method, path);
//限流
ClientFailure.TOO_MANY_REQUESTS.requireNon(apiDetail.getRateLimit() > 0 && rateLimit(apiDetail.getId(), apiDetail.getRateLimit()));
//解析token
TokenIdentity tokenIdentity = tokenService.getTokenIdentity(request);
if (tokenIdentity != null) {
session.setUserid(tokenIdentity.userid);
session.setRoleId(tokenIdentity.roleId);
}
if (apiDetail.isLogin()) {
TokenInfo tokenInfo = tokenService.getTokenInfo(tokenIdentity);
ClientFailure.UNAUTHORIZED.requireNon(!tokenService.verify(tokenInfo, session));
session.setLogin(tokenService.isLogin(tokenInfo));
//登录验证
ClientFailure.UNAUTHORIZED.requireNon(!session.getLogin());
//权限验证
authService.checkApiPermission(session.getRoleId(), apiDetail.getId());
} else session.setLogin(tokenService.isLogin(session));
session.setDba(authService.isDba(session.getRoleId()));
//判断是否禁用
ClientFailure.FORBIDDEN.requireNon(!apiDetail.isEnabled() && !session.isDba());
//判断是否重复提交
if (apiDetail.getIntervalLimit() > 0 && session.getUserid() != null)
ClientFailureMsg.requireNon(intervalLimit(apiDetail.getId(), session.getUserid(), apiDetail.getIntervalLimit() * 1000L), "重复提交");
return true;
}
protected abstract ApiDetail getApiDetail(String appName, String method, String path);
protected boolean ignore(String appName, String method, String path) {
return false;
}
protected boolean rateLimit(long apiId, int rateLimit) {
return false;
}
protected boolean intervalLimit(long apiId, long userid, long intervalLimitMillis) {
return false;
}
}