feat:避免反复查询,加快速度
This commit is contained in:
parent
db2ff0519a
commit
eb23176b78
@ -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时,校验jwt。redis也需要存在
|
// 存在jwt时,校验jwt。redis也需要判断是否在黑名单
|
||||||
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();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user