JWT身份验证,而无需获取每个请求的用户详细信息 [英] JWT authentication without fetching user details on each request

查看:199
本文介绍了JWT身份验证,而无需获取每个请求的用户详细信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm implementing JWT authentication in Spring Security. I have predefined roles, eg. regular user, admin etc.

我有以下令牌有效载荷:

I have following payload of token:

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

到目前为止,我看到的大多数实现都基于id/username/email从数据库中检索用户详细信息,然后使用此数据来创建身份验证(例如,通过对UsernamePasswordAuthenticationToken进行身份验证). 对我来说,这实际上是一种更可取的方法,因为我总是拥有最新的特权和限制(例如,是否禁止用户使用),并且与收益相比,时间开销并不算太大.

Most of the implementations I saw so far retrieve user details from database based on id/username/email and then use this data to create authentication (eg. by authenticating UsernamePasswordAuthenticationToken). For me it's actually a preferrable way to go, because I always have up to date privileges and restrictions (eg. whether user was banned) and time overhead is not so big compared to benefits.

我很好奇我如何仅基于传入请求中包含的角色(在其授权标头令牌中)使用Spring Security来实现授权.我希望能够在正确路由请求后访问控制器中的用户标识符.仅根据检查到期时间和角色有效性进行的令牌验证就足够了吗?

I'm just curious how could I implement authorization with Spring Security based only on roles included in incoming request (in its authorization header token). I want just to be able to access user identifier in controller after the request is routed appropriately. Would token validation based only on checking expiration time and roles validity be sufficient?

推荐答案

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

Since the information about the user's roles are part of your token (in the scopesclaim), it's possible to create the authentication object based on the token alone, without further access to the database.

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

In the following example, the createAuthentication() method transforms the token into a Spring Security Authentication object.

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 ...
    }

}

这篇关于JWT身份验证,而无需获取每个请求的用户详细信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆