com.lx.boot.web.DefaultSecurityInterceptor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of lxboot3 Show documentation
Show all versions of lxboot3 Show documentation
使用文档: https://a7fi97h1rc.feishu.cn/docx/X3LRdtLhkoXQ8hxgXDQc2CLOnEg?from=from_copylink
package com.lx.boot.web;
import com.lx.annotation.Note;
import com.lx.boot.OS;
import com.lx.boot.web.annotation.Auth;
import com.lx.constant.DefaultResult;
import com.lx.entity.ExpireCache;
import com.lx.entity.Result;
import com.lx.entity.UserInfo;
import com.lx.util.LX;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import java.util.Optional;
import static com.lx.constant.DefaultBaseConstant.*;
/**
* @author ylx
* @description 权限拦截器
* @date 2017/11/17
* @since 1.0
*/
@Slf4j
public class DefaultSecurityInterceptor implements HandlerInterceptor {
@Autowired
private AuthUtil authUtil;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (!(handler instanceof HandlerMethod)) {
return true;
}
String url = request.getServletPath();
//根据token查询用户信息
UserInfo userInfo = OS.getRealUserInfo();
HandlerMethod handlerMethod = (HandlerMethod) handler;
Auth auth = Optional.ofNullable(handlerMethod.getMethod().getAnnotation(Auth.class)).orElse(handlerMethod.getMethod().getDeclaringClass().getAnnotation(Auth.class));
if (auth != null && !checkAuth(auth, userInfo, url,request,response)){
return false;
}
// 用户不存在
if (LX.isEmpty(userInfo)){
//开发环境
if (isDev(request)){
return true;
}
//获取方法上或者类上的注解
if (auth != null && !auth.value()){
return true;
}
//无需登录的接口
if (isNotAuthUrl(url)){
return true;
}
// 判断是不是系统接口
if (isSysMethod(request, auth)){
OS.allowAccessKeyClear(url);
return true;
}
log.warn("请重新登录! 请检查是否使用 AuthUtil.createToken/createJwtToken 创建用户登录信息!");
setReturnInfo(response, DefaultResult.TOKERPAST.getResult());
return false;
}
return true;
}
/** 说明: 无需登录的接口
* @author ylx 2023/3/10 14:02 */
public static boolean isNotAuthUrl(String url) {
//无需登录接口
String notAuthPattern = OS.getProperty(SERVER_NOTAUTH);
if ((LX.isNotEmpty(notAuthPattern) && url.matches(notAuthPattern))){
return true;
}
//无需登录加密接口 或 第三方接口
return SecurityFilter.isNotAuthAndEncryptionUrl(url) || SecurityFilter.isApiUrl(url);
}
@Note("缓存系统接口的nonce, 分布式部署需要使用redis")
private static ExpireCache nonceExpireCache = new ExpireCache(5000,600_000);
//说明: 内置方法进行认证 通过header sysAuthorization 传 des(密码+时间戳) 进行对比
/** @author ylx 2022/12/2 16:30 */
private boolean isSysMethod(HttpServletRequest request, Auth auth) {
if (auth != null && auth.isSysMethod()){
try {
if(!OS.allowAccessTo(request.getServletPath(),"5","300")){
//300秒内错误5次就锁定不能继续调用
return false;
}
String key = request.getHeader(SYS_AUTHORIZATION);
String timestamp = request.getHeader(SYS_AUTHORIZATION_TIMESTAMP);
String nonce = request.getHeader(SYS_AUTHORIZATION_NONCE);
if (LX.isEmpty(key) || LX.isEmpty(nonce) || LX.isEmpty(timestamp)){
return false;
}
if (nonceExpireCache.get(nonce) != null){
return false;
}
nonceExpireCache.put(nonce,"1");
Long t = Long.parseLong(timestamp);
boolean forMoreThan = (System.currentTimeMillis() - t)/(1000*60) > 15;
LX.exMsg(forMoreThan,"时间大于15分钟,不能调用接口");
String dKey = LX.desEncrypt(OS.getProperty(SERVER_USER_KEY, DEFAULT_SERVER_USER_KEY) + timestamp+"-"+nonce, "yzy@123@");
return dKey.equals(key);
}catch (Exception e){
log.error("判断系统接口登录异常:",e);
}
}
return false;
}
//说明: 对@Auth特殊判断
/** @author ylx 2022/8/26 10:40 */
private boolean checkAuth(Auth auth, UserInfo userInfo, String url, HttpServletRequest request, HttpServletResponse response) throws InstantiationException, IllegalAccessException {
// 判断IP
if (LX.isNotEmpty(auth.ipWhiteListRegexApplicationKey())){
String ip = OS.getIp(request);
String ipWhiteList = OS.getProperty(auth.ipWhiteListRegexApplicationKey());
if (LX.isEmpty(ip) || LX.isEmpty(ipWhiteList) || !ip.matches(ipWhiteList)){
log.info("ip:{}, 接口IP注解配置:{}, 实际配置:{}",ip, auth.ipWhiteListRegexApplicationKey(),ipWhiteList);
setReturnInfo(response, DefaultResult.IP_LIMIT.setMessage("调用IP异常:"+ip));
return false;
}
}
// 根据IP限制方法调用次数
if (LX.isNotEmpty(auth.callNumberByIp())){
String ip = OS.getIp(request);
if (!OS.allowAccessByCallFrequency(ip+":"+url, auth.callNumberByIp())){
setReturnInfo(response, DefaultResult.CALL_LIMIT.setMessage("调用次数超过限制:"+auth.callNumberByIp()));
return false;
}
}
if (LX.isNotEmpty(userInfo)){
// 判断是否有权限
if (LX.isNotEmpty(auth.allowUserTypeRegex())){
if (LX.isEmpty(userInfo.getUserType()) || !userInfo.getUserType().matches(auth.allowUserTypeRegex())){
log.info("用户信息:{}, 接口注解配置:{}",userInfo, auth.allowUserTypeRegex());
setReturnInfo(response, DefaultResult.ACCESSERROR.getResult());
return false;
}
}
// 根据用户ID限制方法调用次数
if (LX.isNotEmpty(auth.callNumberByUser())){
if (!OS.allowAccessByCallFrequency(userInfo.getUserId()+":"+url, auth.callNumberByUser())){
setReturnInfo(response, DefaultResult.CALL_LIMIT.setMessage("调用次数超过限制:"+auth.callNumberByUser()));
return false;
}
}
}
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
// log.info("结束调用微服务渲染视图");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
//说明:开发调试环境
/**{ ylx } 2021/6/15 16:26 */
private static boolean isDev(HttpServletRequest request){
return "dev".equals(OS.getEnv()) && "0".equals(request.getHeader(AUTHORIZATION));
}
private void setReturnInfo(HttpServletResponse response, Result info){
try {
//返回响应
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(LX.toJSONString(info));
} catch (Exception e) {
log.error("过滤器拦截失败!",e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy