【问题标题】:Role Based Authorization using JWT - Spring security使用 JWT 的基于角色的授权 - Spring 安全性
【发布时间】:2020-11-29 17:25:40
【问题描述】:

希望你们都做得很好!我正在 Spring Boot 中实现基于 JWT 角色的授权。

我已经能够实现它。我正在关注的教程是这个

https://github.com/only2dhir/spring-security-jwt

用户注册成功。然后我为该用户分配一个像 ADMIN 这样的角色。

现在我有了这个 api @GetMapping("/users")

应该由管理员访问。但是当我访问这个 api 时,它给了我这个错误

java.lang.NullPointerException: Cannot invoke "Object.toString()" because the return value of 
"io.jsonwebtoken.Claims.get(Object)" is null 

这个错误来自这些方法:

JwtTokenUtil:

 public static final String AUTHORITIES_KEY = "scopes";
 UsernamePasswordAuthenticationToken getAuthentication(final String token, final Authentication 
  exsitingAuth, final UserDetails userDetails){

    final JwtParser jwtParser = Jwts.parser().setSigningKey(secret);

    final Jws<Claims> claimsJws = jwtParser.parseClaimsJws(token);

    final Claims claims = claimsJws.getBody();

    final Collection<? extends GrantedAuthority> authorities=
    java.util.Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(","))
         .map(SimpleGrantedAuthority::new)
         .collect(Collectors.toList());

    return new UsernamePasswordAuthenticationToken(userDetails, "", authorities);
}

这一行给出错误

 java.util.Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(","))

创建身份验证:

 UserDetailsWithToken UserDetailsWithToken = new UserDetailsWithToken();
    authenticate(authenticationRequest.getEmpID(), 
 authenticationRequest.getPswd());

    final UserDetails userDetails = 
 userDetailsService.loadUserByUsername(authenticationRequest.getEmpID());

    
    final Authentication authentication = authenticationManager.authenticate(
            new UsernamePasswordAuthenticationToken(
                authenticationRequest.getEmpID(),
                authenticationRequest.getPswd()
            )
    );
    SecurityContextHolder.getContext().setAuthentication(authentication);
    
    final String token = 
   jwtTokenUtil.generateToken(userDetails,authentication);
    

【问题讨论】:

  • 尝试将claims.get(AUTHORITIES_KEY) 打印到您的日志或控制台。它看起来像什么?
  • 打印到日志是什么意思?我正在使用邮递员测试我的api。我的应用程序还没有前端。 @TimBiegeleisen
  • 能否提供创建token的代码?
  • @gaetanTEMATE 请查看我更新的问题

标签: spring-boot spring-security jwt


【解决方案1】:

我猜你缺少添加权限。

在此处查看代码 .... 我的答案是创建一个令牌 ...

public String generateToken(UserDetails userDetails, Authentication 
   authentication) {
    List<String> roles = user.getAuthorities()
                .stream()
                .map(GrantedAuthority::getAuthority)
                .collect(Collectors.toList());
            return doGenerateToken(userDetails.getUsername(), roles);
}

    

另一种方法

public String doGenerateToken(String username, List<String> roles) {
        try {
            Claims claims = Jwts.claims().setSubject(username);
            claims.put("username", roles);
            claims.put(AUTHORITIES_KEY, username);
            return Jwts.builder()
                    .setClaims(claims)
                    .setExpiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY * 120000))
                    .signWith(SignatureAlgorithm.HS512, secret).compact();
                    .compact();
        } catch (InvalidKeyException e) {
            logger.error(e.getMessage(), e);
        }
        return "";
    }

添加权限字符串并将其传递给 doGenerateToken 方法。

谢谢,

阿图尔

【讨论】:

  • 我按照你说的做了。它给了我这个错误A granted authority textual representation is required你能帮忙吗? @Atul
  • 我修改了答案,您需要将 Map 更改为 Map ...。我猜这会起作用。
  • 将其更改为 Map&lt;String, String&gt; 会给我带来很多其他错误。以前它正在工作,但只是给了我这个错误A granted authority textual representation is required @Atul
  • 编辑了我的答案...需要更改一些常量,但从逻辑上讲,它将帮助您创建令牌
  • 我刚刚添加了claim(AUTHORITIES_KEY, authorities) 我的令牌正在完美创建我现在得到的唯一错误是A granted authority textual representation is required
【解决方案2】:

在您的代码中,您没有在 jwt 令牌中设置权限尝试设置它:


    return doGenerateToken(authorities, userDetails.getUsername());
...

private String doGenerateToken(String authorities, String subject) {
        return
            Jwts.builder()
                .claim(AUTHORITIES_KEY, authorities)
                .setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
                .setExpiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY * 120000))
                .signWith(SignatureAlgorithm.HS512, secret).compact();
    }

确保正确创建您的身份验证


        UsernamePasswordAuthenticationToken authenticationToken =
            new UsernamePasswordAuthenticationToken("username", "myPassword");

        Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
        SecurityContextHolder.getContext().setAuthentication(authentication);
String jwt = tokenProvider.generateToken(authentication.getPrincipal(), authentication);

【讨论】:

  • 我照你说的做了,但它给出了这个错误A granted authority textual representation is required请帮助@gaetanTEMATE
  • 这取决于您如何创建身份验证身份验证,确保它看起来像这样,(更新答案)
  • 请查看我更新的问题。你能告诉我我是否正确地创建了身份验证。或者我需要改变什么? @gaetanTEMATE
猜你喜欢
  • 2020-07-09
  • 2017-12-14
  • 2017-04-04
  • 2018-04-17
  • 2020-09-13
  • 2016-07-20
  • 2017-06-24
  • 2020-06-16
  • 2018-11-01
相关资源
最近更新 更多