|
|
@@ -12,6 +12,8 @@ import jakarta.servlet.ServletException;
|
|
|
import jakarta.servlet.http.HttpServletRequest;
|
|
|
import jakarta.servlet.http.HttpServletResponse;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.data.redis.core.RedisTemplate;
|
|
|
import org.springframework.security.authentication.CredentialsExpiredException;
|
|
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
|
|
import org.springframework.security.core.context.SecurityContextHolder;
|
|
|
@@ -21,6 +23,7 @@ import org.springframework.web.filter.OncePerRequestFilter;
|
|
|
|
|
|
import java.io.IOException;
|
|
|
import java.util.Map;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
/**
|
|
|
* @author: Leonezhurui
|
|
|
@@ -35,13 +38,24 @@ public class JWTAuthenticationFilter extends OncePerRequestFilter {
|
|
|
private final JWTTokenUtil jwtTokenUtil;
|
|
|
private final MyUserDetailService userDetailService;
|
|
|
private final UserService userService;
|
|
|
+ private final RedisTemplate<String, Object> redisTemplate;
|
|
|
+
|
|
|
+ @Value("${jwt.portal-sync.enabled:true}")
|
|
|
+ private boolean portalSyncEnabled;
|
|
|
+
|
|
|
+ @Value("${jwt.portal-sync.throttle-seconds:60}")
|
|
|
+ private long portalSyncThrottleSeconds;
|
|
|
|
|
|
private final MyAuthenticationEntryPoint authenticationEntryPoint = new MyAuthenticationEntryPoint();
|
|
|
|
|
|
- public JWTAuthenticationFilter(JWTTokenUtil jwtTokenUtil, MyUserDetailService userDetailService, UserService userService) {
|
|
|
+ public JWTAuthenticationFilter(JWTTokenUtil jwtTokenUtil,
|
|
|
+ MyUserDetailService userDetailService,
|
|
|
+ UserService userService,
|
|
|
+ RedisTemplate<String, Object> redisTemplate) {
|
|
|
this.jwtTokenUtil = jwtTokenUtil;
|
|
|
this.userDetailService = userDetailService;
|
|
|
this.userService = userService;
|
|
|
+ this.redisTemplate = redisTemplate;
|
|
|
}
|
|
|
|
|
|
// 原登录jwtTokenUtil.parseToken(token)获得的是学号,门户是手机号
|
|
|
@@ -60,7 +74,7 @@ public class JWTAuthenticationFilter extends OncePerRequestFilter {
|
|
|
String phone = jwtTokenUtil.parseToken(token);
|
|
|
Map<String, Object> userInfoMap = jwtTokenUtil.parseClaim(token).getBody().get("user_info", Map.class);
|
|
|
// 不为空则认为是门户请求,此时同步用户信息
|
|
|
- if(userInfoMap != null){
|
|
|
+ if (userInfoMap != null && shouldSyncUserInfo(userInfoMap, phone)) {
|
|
|
syncUserInfo(userInfoMap, phone);
|
|
|
}
|
|
|
|
|
|
@@ -109,4 +123,28 @@ public class JWTAuthenticationFilter extends OncePerRequestFilter {
|
|
|
userService.updateUserByPid(pid, update);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ private boolean shouldSyncUserInfo(Map<String, Object> userInfoMap, String phone) {
|
|
|
+ if (!portalSyncEnabled || portalSyncThrottleSeconds <= 0) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ Object pid = userInfoMap.get("id");
|
|
|
+ String syncTarget = pid == null ? phone : pid.toString();
|
|
|
+ String throttleKey = "auth:portal-sync:" + syncTarget;
|
|
|
+
|
|
|
+ try {
|
|
|
+ Boolean shouldSync = redisTemplate.opsForValue().setIfAbsent(
|
|
|
+ throttleKey,
|
|
|
+ System.currentTimeMillis(),
|
|
|
+ portalSyncThrottleSeconds,
|
|
|
+ TimeUnit.SECONDS
|
|
|
+ );
|
|
|
+ return Boolean.TRUE.equals(shouldSync);
|
|
|
+ } catch (Exception e) {
|
|
|
+ // Redis is an optimization here; if unavailable we keep current auth behavior.
|
|
|
+ log.warn("shouldSyncUserInfo redis throttle failed, fallback to immediate sync. key={}", throttleKey, e);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|