JWT 身份验证,无需获取每个请求的用户详细信息



我正在Spring Security中实现JWT身份验证。 我有预定义的角色,例如。普通用户、管理员等

我有以下令牌有效载荷:

{
"sub": "nick",
"iat": "<some_date>",
"exp": "<some_date+1h>",
"scopes": [
"ROLE_USER",
"ROLE_ADMIN"
]
}

到目前为止,我看到的大多数实现都根据id/用户名/电子邮件从数据库中检索用户详细信息,然后使用此数据来创建身份验证(例如,通过身份验证UsernamePasswordAuthenticationToken(。 对我来说,这实际上是一种可取的方式,因为我总是拥有最新的特权和限制(例如,用户是否被禁止(,并且与福利相比,时间开销并不大。

我只是好奇如何仅基于传入请求中包含的角色(在其授权标头令牌中(使用 Spring 安全性实现授权。我只想在正确路由请求后能够访问控制器中的用户标识符。仅基于检查过期时间和角色有效性的令牌验证是否足够?

由于有关用户角色的信息是令牌的一部分(在scopes声明中(,因此可以仅基于令牌创建身份验证对象,而无需进一步访问数据库。

在下面的示例中,createAuthentication()方法将令牌转换为 Spring 安全Authentication对象。

public class JWTFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String jwt = // resolveToken(httpServletRequest);
this.createAuthentication(jwt).ifPresent(authentication -> {
SecurityContextHolder.getContext().setAuthentication(authentication);
});
filterChain.doFilter(servletRequest, servletResponse);
}

public Optional<Authentication> createAuthentication(String token) {
Jws<Claims> jwsClaims = validateToken(token);
if (jwsClaims == null) {
return Optional.empty();
}
Claims claims = jwsClaims.getBody();
String scopesString = claims.get("scopes").toString();
String[] authStrings = scopesString.split(",");
Collection<? extends GrantedAuthority> authorities =
Arrays.stream(authStrings)
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
String subject = claims.getSubject();
org.springframework.security.core.userdetails.User principal = new User(subject, "", authorities);
return Optional.of(new UsernamePasswordAuthenticationToken(principal, token, authorities));
}
private Jws<Claims> validateToken(String authToken) {
try {
Jws<Claims> claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(authToken);
return claims;
} catch ...
}
}

最新更新