feat:避免反复查询,加快速度

This commit is contained in:
wangyu 2022-10-02 21:00:34 +08:00
parent db2ff0519a
commit eb23176b78
2 changed files with 23 additions and 33 deletions

View File

@ -3,8 +3,8 @@ package com.flyfish.framework.configuration.jwt;
import com.flyfish.framework.service.MongoUserDetailsService; import com.flyfish.framework.service.MongoUserDetailsService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.web.server.context.ServerSecurityContextRepository; import org.springframework.security.web.server.context.ServerSecurityContextRepository;
import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
@ -20,23 +20,21 @@ public class JwtSecurityContextRepository implements ServerSecurityContextReposi
@Resource @Resource
private TokenProvider tokenProvider; private TokenProvider tokenProvider;
@Override @Override
public Mono<SecurityContext> load(ServerWebExchange serverWebExchange) { public Mono<SecurityContext> load(ServerWebExchange serverWebExchange) {
ServerHttpRequest request = serverWebExchange.getRequest(); ServerHttpRequest request = serverWebExchange.getRequest();
String jwt = tokenProvider.retrieveToken(serverWebExchange).orElse(null); String jwt = tokenProvider.retrieveToken(serverWebExchange).orElse(null);
URI requestURI = request.getURI(); URI requestURI = request.getURI();
// 存在jwt时校验jwtredis也需要存在 // 存在jwt时校验jwtredis也需要判断是否在黑名单
return tokenProvider.validateToken(jwt).flatMap(authorized -> { return tokenProvider.validateToken(jwt).flatMap(userId -> {
if (authorized) { log.debug("set Authentication to security context for '{}', uri: {}", userId, requestURI);
// token即将过期续租 return userDetailsService.findByUsername(userId)
Authentication authentication = tokenProvider.getAuthentication(jwt); .map(userDetails -> {
log.debug("set Authentication to security context for '{}', uri: {}", authentication.getName(), requestURI); SecurityContextImpl securityContext = new SecurityContextImpl();
return userDetailsService.findByUsername(authentication.getName()) securityContext.setAuthentication(tokenProvider.getAuthentication(userDetails));
.flatMap(userDetails -> userDetailsService.loadContext(userDetails)); return securityContext;
} else { });
log.debug("no valid JWT token found, uri: {}", requestURI);
return Mono.empty();
}
}); });
} }

View File

@ -15,16 +15,13 @@ import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.User;
import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.security.Key; import java.security.Key;
import java.time.Duration; import java.time.Duration;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -145,20 +142,12 @@ public class TokenProvider implements InitializingBean {
/** /**
* token解析第一步获取认证此处通过claims就能知道token是哪个端的 * token解析第一步获取认证此处通过claims就能知道token是哪个端的
* *
* @param token token * @param userDetails 用户详情
* @return 结果 * @return 结果
*/ */
public Authentication getAuthentication(String token) { public Authentication getAuthentication(UserDetails userDetails) {
Claims claims = parseToken(token); return new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(),
userDetails.getAuthorities());
Collection<? extends GrantedAuthority> authorities =
Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(","))
.filter(StringUtils::isNotBlank)
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
User principal = new User(claims.getSubject(), "", authorities);
return new UsernamePasswordAuthenticationToken(principal, token, authorities);
} }
/** /**
@ -179,13 +168,16 @@ public class TokenProvider implements InitializingBean {
return TOKEN_BLOCK_PREFIX + jti; return TOKEN_BLOCK_PREFIX + jti;
} }
public Mono<Boolean> validateToken(String authToken) { public Mono<String> validateToken(String authToken) {
if (StringUtils.isBlank(authToken)) { if (StringUtils.isBlank(authToken)) {
return Mono.just(false); log.debug("no valid JWT token found");
return Mono.empty();
} }
try { try {
Claims claims = parseToken(authToken); Claims claims = parseToken(authToken);
return reactiveRedisOperations.hasKey(getCacheKey(claims.getId())).map(exists -> !exists); return reactiveRedisOperations.hasKey(getCacheKey(claims.getId()))
.filter(result -> !result)
.thenReturn(claims.getSubject());
} catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) { } catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) {
log.info("Invalid JWT signature."); log.info("Invalid JWT signature.");
log.trace("Invalid JWT signature trace: {}", e, e); log.trace("Invalid JWT signature trace: {}", e, e);
@ -202,6 +194,6 @@ public class TokenProvider implements InitializingBean {
log.info("Token解析失败"); log.info("Token解析失败");
log.trace("Token解析失败: {}", e, e); log.trace("Token解析失败: {}", e, e);
} }
return Mono.just(false); return Mono.empty();
} }
} }