问题描述
在Spring Webflux应用程序中,我具有以下“ AuthenticationManager”实现。概括地说,以下是其要执行的操作-
-
某些url路径在prop文件中配置为需要基本身份验证,而其他则需要承载令牌。
-
对于基本身份验证,BcryptPasswordEncoder.matches方法用于将传入密码与存储在prop文件中的已编码密码进行比较。
-
对于承载令牌身份验证,正在使用io.jsonwebtoken库来验证令牌。
@Component public class AuthenticationManager implements ReactiveAuthenticationManager { /** The jwt util. */ @Autowired private JWTUtil jwtUtil; @Override public Mono<Authentication> authenticate(Authentication authobj) { return Mono.just(authobj).flatMap(authentication -> { String credentials = authentication.getCredentials().toString(); String path = authentication.getPrincipal().toString(); BasicAuthPath basicAuthPath = jwtUtil.isBasicAuthUrl(path); if (jwtUtil.isBasicScheme(credentials) || jwtUtil.isBearerScheme(credentials)) { if (jwtUtil.isBasicScheme(credentials) && basicAuthPath.isstate()) { credentials = credentials.substring(5); if (jwtUtil.isBasicAuthSuccess(credentials.trim(),basicAuthPath.getPath())) { UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(credentials,null,null); return Mono.just(auth); } else { return Mono.empty(); } } else if (jwtUtil.isBearerTokenAuthUrl(path) && jwtUtil.isBearerScheme(credentials)) { credentials = credentials.substring(7); String username; try { username = jwtUtil.getUsernameFromToken(credentials); } catch (Exception e) { username = null; } if (jwtUtil.validatetoken(credentials)) { Claims claims = jwtUtil.getAllClaimsFromToken(credentials); List<String> rolesMap = claims.get("role",List.class); List<Role> roles = new ArrayList<>(); for (String rolemap : rolesMap) { roles.add(Role.valueOf(rolemap)); } UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(username,roles.stream().map(authority -> new SimpleGrantedAuthority(authority.name())).collect(Collectors.toList())); return Mono.just(auth); } else { return Mono.empty(); } } else { return Mono.empty(); } } return Mono.empty(); }); } }
下面的JwtUtil代码
@Component
@Slf4j
public class JWTUtil implements Serializable {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 1L;
/** The env. */
@Autowired
private Environment env;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private JwtParser jwtParser;
@Autowired
private Key signingKey;
private static final PathPatternParser DEFAULT_PATTERN_PARSER = new PathPatternParser();
/**
* Checks if is basic auth success.
*
* @param inputCredentials the input credentials
* @param path the path
* @return true,if is basic auth success
*/
public boolean isBasicAuthSuccess(String inputCredentials,String path) {
String pathtoprop = pathtoprop(path);
String configpwd = env.getProperty(pathtoprop);
if (StringUtils.isBlank(configpwd)) {
configpwd = env.getProperty(pathtoprop.substring(0,pathtoprop.lastIndexOf(".")));
}
return passwordEncoder.matches(new String(Base64.getDecoder().decode(inputCredentials)),configpwd);
//return true;
}
/**
* Checks if is basic auth url.
*
* @param path the path
* @return true,if is basic auth url
*/
public BasicAuthPath isBasicAuthUrl(String path) {
BasicAuthPath basicAuthPath = new BasicAuthPath();
if (StringUtils.isNotBlank(env.getProperty("gateway.basicauth.urls"))) {
return pathMatcherBasic(StringUtils.split(env.getProperty("gateway.basicauth.urls"),","),path);
}
basicAuthPath.setState(false);
return basicAuthPath;
}
/**
* pathMatcher
*
* @param pathPatterns
* @param path
* @return
*/
private BasicAuthPath pathMatcherBasic(String[] pathPatterns,String path) {
BasicAuthPath basicAuthPath = new BasicAuthPath();
for (String pathPattern : pathPatterns) {
PathPattern pattern = DEFAULT_PATTERN_PARSER.parse(pathPattern);
if (pattern.matches(PathContainer.parsePath(path))) {
basicAuthPath.setState(true);
basicAuthPath.setPath(pathPattern);
return basicAuthPath;
}
}
basicAuthPath.setState(false);
return basicAuthPath;
}
/**
* Checks if is bearer token auth url.
*
* @param path the path
* @return true,if is bearer token auth url
*/
public boolean isBearerTokenAuthUrl(String path) {
if (StringUtils.isNotBlank(env.getProperty("gateway.bearertoken.urls"))
&& pathMatcher(StringUtils.split(env.getProperty("gateway.bearertoken.urls"),path)) {
return true;
}
return false;
}
/**
* pathMatcher
*
* @param pathPatterns
* @param path
* @return
*/
private boolean pathMatcher(String[] pathPatterns,String path) {
for (String pathPattern : pathPatterns) {
PathPattern pattern = DEFAULT_PATTERN_PARSER.parse(pathPattern);
if (pattern.matches(PathContainer.parsePath(path))) {
return true;
}
}
return false;
}
/**
* isBasicScheme
*
* @param credentials
* @return
*/
public boolean isBasicScheme(String credentials) {
if (StringUtils.isNotBlank(credentials) && credentials.startsWith(RestUriConstants.BASIC_TOKE_PREFIX)) {
return true;
}
return false;
}
/**
* isBearerScheme
*
* @param credentials
* @return
*/
public boolean isBearerScheme(String credentials) {
if (StringUtils.isNotBlank(credentials) && credentials.startsWith(RestUriConstants.BEARER_TOKE_PREFIX)) {
return true;
}
return false;
}
/**
* Gets the all claims from token.
*
* @param token the token
* @return the all claims from token
*/
public Claims getAllClaimsFromToken(String token) {
return jwtParser.parseClaimsJws(token).getBody();
}
/**
* Gets the username from token.
*
* @param token the token
* @return the username from token
*/
public String getUsernameFromToken(String token) {
return getAllClaimsFromToken(token).getSubject();
}
/**
* Gets the expiration date from token.
*
* @param token the token
* @return the expiration date from token
*/
public Date getExpirationDateFromToken(String token) {
return getAllClaimsFromToken(token).getExpiration();
}
/**
* Checks if is token expired.
*
* @param token the token
* @return the boolean
*/
private Boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(new Date());
}
/**
* Generate token.
*
* @param user the user
* @return the string
*/
public String generatetoken(User user) {
Map<String,Object> claims = new HashMap<>();
claims.put("role",user.getRoles());
return doGeneratetoken(claims,user.getUsername());
}
/**
* Do generate token.
*
* @param claims the claims
* @param username the username
* @return the string
*/
private String doGeneratetoken(Map<String,Object> claims,String username) {
Long expirationTimeLong = Long.parseLong(env.getProperty("gateway.apollo.token.encryption.exp")); // in second
final Date createdDate = new Date();
final Date expirationDate = new Date(createdDate.getTime() + expirationTimeLong * 1000);
return Jwts.builder().setClaims(claims).setSubject(username).setIssuedAt(createdDate).setExpiration(expirationDate).signWith(signingKey)
.compact();
}
/**
* Validate token.
*
* @param token the token
* @return the boolean
*/
public Boolean validatetoken(String token) {
Boolean result = false;
try {
result = !isTokenExpired(token);
} catch (Exception e) {
log.error("Exception in validatetoken - {}",token);
}
return result;
}
private String pathtoprop(String path) {
return "gateway.basicauth.credentials" + path.replace('/','.');
}
}
在使用大量并行线程执行PST期间,观察到了较高的cpu利用率。我认为可能是因为上面的许多代码都被阻止了。如果是这样,那么有人可以提供有关如何以响应方式重构此代码的指针的帮助吗?我是否应该使用如下所示的线程池以获得更好的性能-
Mono.just(authobj).publishOn(Schedulers.newParallel("password-encoder",Schedulers.DEFAULT_POOL_SIZE,true);).......
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)