From ff169f9a0417b73f0afac554cf2f9d048ac56c80 Mon Sep 17 00:00:00 2001
From: 无关风月 <443237572@qq.com>
Date: 星期一, 19 八月 2024 20:57:08 +0800
Subject: [PATCH] Merge branch 'master' of http://120.76.84.145:10101/gitblit/r/java/mx_charging_pile

---
 ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java |  305 +++++++++++++++++++++++++++++++++-----------------
 1 files changed, 200 insertions(+), 105 deletions(-)

diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java
index e829417..f46470c 100644
--- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java
+++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java
@@ -1,18 +1,17 @@
 package com.ruoyi.gateway.filter;
 
-import com.alibaba.fastjson.JSONObject;
-import org.apache.commons.codec.binary.Base64;
+import com.ruoyi.account.api.feignClient.AppUserClient;
+import com.ruoyi.account.api.model.TAppUser;
+import com.ruoyi.system.api.domain.SysUser;
+import com.ruoyi.system.api.feignClient.SysUserClient;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
 import org.springframework.cloud.gateway.filter.GatewayFilterChain;
 import org.springframework.cloud.gateway.filter.GlobalFilter;
 import org.springframework.core.Ordered;
-import org.springframework.core.io.buffer.DataBuffer;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.server.reactive.ServerHttpRequest;
-import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
 import org.springframework.stereotype.Component;
 import org.springframework.web.server.ServerWebExchange;
 import com.ruoyi.common.core.constant.CacheConstants;
@@ -25,113 +24,209 @@
 import com.ruoyi.common.redis.service.RedisService;
 import com.ruoyi.gateway.config.properties.IgnoreWhiteProperties;
 import io.jsonwebtoken.Claims;
-import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicReference;
+import javax.annotation.Resource;
+import java.util.HashMap;
+import java.util.Map;
+
 
 /**
  * 网关鉴权
- * 
+ *
  * @author ruoyi
  */
 @Component
 public class AuthFilter implements GlobalFilter, Ordered {
-    private static final Logger log = LoggerFactory.getLogger(AuthFilter.class);
-
-    // 排除过滤的 uri 地址,nacos自行添加
-    @Autowired
-    private IgnoreWhiteProperties ignoreWhite;
-
-    @Autowired
-    private RedisService redisService;
-
-
-    @Override
-    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
-        ServerHttpRequest request = exchange.getRequest();
-        ServerHttpRequest.Builder mutate = request.mutate();
-
-        String url = request.getURI().getPath();
-        // 跳过不需要验证的路径
-        if (StringUtils.matches(url, ignoreWhite.getWhites())) {
-            return chain.filter(exchange);
-        }
-        String token = getToken(request);
-        if (StringUtils.isEmpty(token)) {
-            return unauthorizedResponse(exchange, "令牌不能为空");
-        }
-        Claims claims = JwtUtils.parseToken(token);
-        if (claims == null) {
-            return unauthorizedResponse(exchange, "令牌已过期或验证不正确!");
-        }
-        String userkey = JwtUtils.getUserKey(claims);
-        boolean islogin = redisService.hasKey(getTokenKey(userkey));
-        if (!islogin) {
-            return unauthorizedResponse(exchange, "登录状态已过期");
-        }
-        String userid = JwtUtils.getUserId(claims);
-        String username = JwtUtils.getUserName(claims);
-        if (StringUtils.isEmpty(userid) || StringUtils.isEmpty(username)) {
-            return unauthorizedResponse(exchange, "令牌验证失败");
-        }
-
-        // 设置用户信息到请求
-        addHeader(mutate, SecurityConstants.USER_KEY, userkey);
-        addHeader(mutate, SecurityConstants.DETAILS_USER_ID, userid);
-        addHeader(mutate, SecurityConstants.DETAILS_USERNAME, username);
-        // 内部请求来源参数清除
-        removeHeader(mutate, SecurityConstants.FROM_SOURCE);
-        return chain.filter(exchange.mutate().request(mutate.build()).build());
-    }
-
-    private void addHeader(ServerHttpRequest.Builder mutate, String name, Object value) {
-        if (value == null) {
-            return;
-        }
-        String valueStr = value.toString();
-        String valueEncode = ServletUtils.urlEncode(valueStr);
-        mutate.header(name, valueEncode);
-    }
-
-    private void removeHeader(ServerHttpRequest.Builder mutate, String name) {
-        mutate.headers(httpHeaders -> httpHeaders.remove(name)).build();
-    }
-
-    private Mono<Void> unauthorizedResponse(ServerWebExchange exchange, String msg) {
-        log.error("[鉴权异常处理]请求路径:{}", exchange.getRequest().getPath());
-        return ServletUtils.webFluxResponseWriter(exchange.getResponse(), msg, HttpStatus.UNAUTHORIZED);
-    }
-
-    /**
-     * 获取缓存key
-     */
-    private String getTokenKey(String token)
-    {
-        return CacheConstants.LOGIN_TOKEN_KEY + token;
-    }
-
-    /**
-     * 获取请求token
-     */
-    private String getToken(ServerHttpRequest request) {
-        String token = request.getHeaders().getFirst(TokenConstants.AUTHENTICATION);
-        // 如果前端设置了令牌前缀,则裁剪掉前缀
-        if (StringUtils.isNotEmpty(token) && token.startsWith(TokenConstants.PREFIX))
-        {
-            token = token.replaceFirst(TokenConstants.PREFIX, StringUtils.EMPTY);
-        }
-        return token;
-    }
-    
-    
-    @Override
-    public int getOrder()
-    {
-        return -300;
-    }
+	private static final Logger log = LoggerFactory.getLogger(AuthFilter.class);
+	
+	// 排除过滤的 uri 地址,nacos自行添加
+	@Autowired
+	private IgnoreWhiteProperties ignoreWhite;
+	
+	@Autowired
+	private RedisService redisService;
+	
+	@Resource
+	private AppUserClient appUserClient;
+	
+	@Resource
+	private SysUserClient sysUserClient;
+	
+	
+	
+	@Override
+	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+		ServerHttpRequest request = exchange.getRequest();
+		ServerHttpRequest.Builder mutate = request.mutate();
+		
+		String url = request.getURI().getPath();
+		// 跳过不需要验证的路径
+		if (StringUtils.matches(url, ignoreWhite.getWhites())) {
+			return chain.filter(exchange);
+		}
+		//防抖校验
+		try {
+			antiShake(request);
+		}catch (Exception e){
+			log.error("[重复提交]请求路径:{}", exchange.getRequest().getPath());
+			return ServletUtils.webFluxResponseWriter(exchange.getResponse(), e.getMessage(), HttpStatus.SUCCESS);
+		}
+		
+		//校验账户是否有效
+		try {
+			verifyToken(request);
+			verifyAccount(request);
+		}catch (Exception e){
+			return unauthorizedResponse(exchange, e.getMessage());
+		}
+		String token = getToken(request);
+		Claims claims = JwtUtils.parseToken(token);
+		String userkey = JwtUtils.getUserKey(claims);
+		String userid = JwtUtils.getUserId(claims);
+		String username = JwtUtils.getUserName(claims);
+		
+		// 设置用户信息到请求
+		addHeader(mutate, SecurityConstants.USER_KEY, userkey);
+		addHeader(mutate, SecurityConstants.DETAILS_USER_ID, userid);
+		addHeader(mutate, SecurityConstants.DETAILS_USERNAME, username);
+		// 内部请求来源参数清除
+		removeHeader(mutate, SecurityConstants.FROM_SOURCE);
+		return chain.filter(exchange.mutate().request(mutate.build()).build());
+	}
+	
+	private void addHeader(ServerHttpRequest.Builder mutate, String name, Object value) {
+		if (value == null) {
+			return;
+		}
+		String valueStr = value.toString();
+		String valueEncode = ServletUtils.urlEncode(valueStr);
+		mutate.header(name, valueEncode);
+	}
+	
+	private void removeHeader(ServerHttpRequest.Builder mutate, String name) {
+		mutate.headers(httpHeaders -> httpHeaders.remove(name)).build();
+	}
+	
+	private Mono<Void> unauthorizedResponse(ServerWebExchange exchange, String msg) {
+		log.error("[鉴权异常处理]请求路径:{}", exchange.getRequest().getPath());
+		return ServletUtils.webFluxResponseWriter(exchange.getResponse(), msg, HttpStatus.UNAUTHORIZED);
+	}
+	
+	/**
+	 * 获取缓存key
+	 */
+	private String getTokenKey(String token) {
+		return CacheConstants.LOGIN_TOKEN_KEY + token;
+	}
+	
+	/**
+	 * 获取请求token
+	 */
+	private String getToken(ServerHttpRequest request) {
+		String token = request.getHeaders().getFirst(TokenConstants.AUTHENTICATION);
+		// 如果前端设置了令牌前缀,则裁剪掉前缀
+		if (StringUtils.isNotEmpty(token) && token.startsWith(TokenConstants.PREFIX)) {
+			token = token.replaceFirst(TokenConstants.PREFIX, StringUtils.EMPTY);
+		}
+		return token;
+	}
+	
+	
+	/**
+	 * 防抖处理
+	 */
+	public void antiShake(ServerHttpRequest request) throws Exception{
+		HttpHeaders headers = request.getHeaders();
+		String client = headers.getFirst("client");
+		String timestamp = headers.getFirst("timestamp");
+		String url = request.getURI().getPath();
+		Map<String, Object> cacheMap = redisService.getCacheMap(client);
+		if(null == cacheMap){
+			cacheMap = new HashMap<>();
+			cacheMap.put(url, timestamp);
+			redisService.setCacheMap(client, cacheMap);
+		}else{
+			Object o = cacheMap.get(url);
+			if(null == o){
+				cacheMap.put(url, timestamp);
+			}else{
+				Long old_timestamp = Long.valueOf(o.toString());
+				Long new_timestamp = Long.valueOf(timestamp);
+				//两个请求时间差小于1秒,判定为重复提交
+				if((new_timestamp - old_timestamp) <= 1000){
+					throw new RuntimeException("重复提交");
+				}else{
+					cacheMap.put(url, timestamp);
+				}
+			}
+			redisService.setCacheMap(client, cacheMap);
+		}
+	}
+	
+	
+	
+	/**
+	 * 验证token
+	 * @param request
+	 * @throws Exception
+	 */
+	public void verifyToken(ServerHttpRequest request) throws Exception{
+		String token = getToken(request);
+		if (StringUtils.isEmpty(token)) {
+			throw new RuntimeException("令牌不能为空");
+		}
+		Claims claims = JwtUtils.parseToken(token);
+		if (claims == null) {
+			throw new RuntimeException("令牌已过期或验证不正确!");
+		}
+		String userkey = JwtUtils.getUserKey(claims);
+		boolean islogin = redisService.hasKey(getTokenKey(userkey));
+		if (!islogin) {
+			throw new RuntimeException("登录状态已过期");
+		}
+		String userid = JwtUtils.getUserId(claims);
+		String username = JwtUtils.getUserName(claims);
+		if (StringUtils.isEmpty(userid) || StringUtils.isEmpty(username)) {
+			throw new RuntimeException("令牌验证失败");
+		}
+	}
+	
+	/**
+	 * 校验账户是否有效
+	 * @param request
+	 * @throws Exception
+	 */
+	public void verifyAccount(ServerHttpRequest request) throws Exception{
+		String token = getToken(request);
+		Claims claims = JwtUtils.parseToken(token);
+		String userid = JwtUtils.getUserId(claims);
+		String userType = JwtUtils.getUserType(claims);
+		//管理后台用户
+		if ("system".equals(userType)) {
+			SysUser sysUser = sysUserClient.getSysUser(Long.valueOf(userid)).getData();
+			if(null == sysUser || "2".equals(sysUser.getDelFlag())){
+				throw new RuntimeException("无效的账户");
+			}
+			if("1".equals(sysUser.getStatus())){
+				throw new RuntimeException("账户已被停用,请联系系统管理员!");
+			}
+		}
+		//小程序用户
+		if ("applet".equals(userType)) {
+			TAppUser appUser = appUserClient.getUserById(Long.valueOf(userid)).getData();
+			if(null == appUser || appUser.getDelFlag() || 3 == appUser.getStatus()){
+				throw new RuntimeException("无效的账户");
+			}
+			if(2 == appUser.getStatus()){
+				throw new RuntimeException("账户已被冻结,请联系系统管理员!");
+			}
+		}
+	}
+	
+	
+	@Override
+	public int getOrder() {
+		return -300;
+	}
 }
\ No newline at end of file

--
Gitblit v1.7.1