使用JWT的基于角色的授权-Spring Security

时间:2020-08-10 05:27:55

标签: spring-boot spring-security jwt

希望大家都做得很好!我正在春季启动中实施基于JWT角色的授权。

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

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

用户已成功注册。然后,我为该用户分配ADMIN之类的角色。

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

应由ADMIN访问。但是,当我访问此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);
    

2 个答案:

答案 0 :(得分:0)

我想您缺少添加权限的人。

在这里查看代码...。我回答了创建令牌的答案...

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方法。

谢谢

Atul

答案 1 :(得分:0)

在您的代码中,您没有在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);