Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring boot Spring Boot JWT令牌基于角色的授权问题_Spring Boot_Spring Security_Jwt_Auth0_Jwt Auth - Fatal编程技术网

Spring boot Spring Boot JWT令牌基于角色的授权问题

Spring boot Spring Boot JWT令牌基于角色的授权问题,spring-boot,spring-security,jwt,auth0,jwt-auth,Spring Boot,Spring Security,Jwt,Auth0,Jwt Auth,所以,我试图实现的是使用JWT令牌的基于角色的授权。这是我正在扩展的教程:https://auth0.com/blog/implementing-jwt-authentication-on-spring-boot/ 现在,我的问题从这里开始:如果(user!=null){这是一个我需要从数据库中获取用户并加载其角色的地方。这不起作用,并且引发了null指针异常。 我确信数据库中有用户,而且我确信UserService正在工作——我在不同的地方使用它,工作正常 期待您的回答 public clas

所以,我试图实现的是使用JWT令牌的基于角色的授权。这是我正在扩展的教程:
https://auth0.com/blog/implementing-jwt-authentication-on-spring-boot/

现在,我的问题从这里开始:
如果(user!=null){
这是一个我需要从数据库中获取用户并加载其角色的地方。这不起作用,并且引发了null指针异常。 我确信数据库中有用户,而且我确信UserService正在工作——我在不同的地方使用它,工作正常

期待您的回答

public class JWTAuthorizationFilter extends BasicAuthenticationFilter {

    public JWTAuthorizationFilter(AuthenticationManager authManager) {
        super(authManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
        String header = req.getHeader(HEADER_STRING);

        if (header == null || !header.startsWith(TOKEN_PREFIX)) {
            chain.doFilter(req, res);
            return;
        }
        UsernamePasswordAuthenticationToken authentication = getAuthentication(req);

        SecurityContextHolder.getContext().setAuthentication(authentication);
        chain.doFilter(req, res);
    }
    private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
        String token = request.getHeader(HEADER_STRING);
        if (token != null) {
            // parse the token.
            String user = JWT.require(Algorithm.HMAC512(SECRET.getBytes()))
                    .build()
                    .verify(token.replace(TOKEN_PREFIX, ""))
                    .getSubject(); //można też getClaims jeśli są w tokenie

            if (user != null) {

                UserService userService = new UserService();
                ApplicationUser applicationUser = userService.getByUsername(user);

                Set<Role> roles = applicationUser.getRoles();
                List<GrantedAuthority> grantedAuths = new ArrayList<>();
                roles.forEach((role) -> {
                    grantedAuths.add(new SimpleGrantedAuthority(role.getName()));
                });

                return new UsernamePasswordAuthenticationToken(user, null, grantedAuths);
            }
            return null;
        }
        return null;
    }
}
这是存储库类:

public interface ApplicationUserRepository extends JpaRepository<ApplicationUser, Long> {
    ApplicationUser findByUsername(String username);
}

您的UserService没有正确注入,因此没有正确初始化,因此出现空指针异常。下面是一些您可以做的事情:

在JWTAuthorization筛选器中,注入用户服务:

public class JWTAuthorizationFilter extends BasicAuthenticationFilter {

    private final IUserService UserService; // create IUserService as below

    public JWTAuthorizationFilter(AuthenticationManager authManager, IUserService userService) {
           super(authManager);
           this.userService = userService;
    }
 (...)
}
从getAuthentication方法中删除UserService UserService=new UserService();因为您已经拥有通过构造函数注入的UserService实例

在您的WebSecurity类(或实现WebSecurity配置适配器的任何类)中,执行相同的操作,注入IUserService:

private final IUserService userService;
public WebSecurity(IUserService userService)
{
       this.userService = userService;
}
在同一个类(WebSecurity)中,您重写了添加JWTAuthorizationFilter的configure方法。现在您必须传递userService

  .addFilter(new JWTAuthorizationFilter(authenticationManager(), userService))
最后,创建一个接口IUserService

public interface IUserService{
      ApplicationUser getByUsername(String username);
}
更改UserService以实现IUserService(删除@Component,因为它实际上是一个@Service)

注意:您可以将接口命名为UserService,将具体实现命名为UserServiceImpl,因为您将始终使用该接口而不是具体实现,因此它的可读性更好


奖励:@Component和@Service annotations之间的区别

谢谢,现在一切都很好!如果你不介意的话,我只需要一个澄清——为什么必须/使用接口(IUserService)?在这种情况下,如果你注入类本身而不是接口,它实际上会起作用(你可以测试它)。在某些情况下(我看到了这一点),我认为让客户机(在本例中是JWTAuthenticationFilter)只与接口对话通常在测试和更干净的设计方面更好。这是一个好问题。
  .addFilter(new JWTAuthorizationFilter(authenticationManager(), userService))
public interface IUserService{
      ApplicationUser getByUsername(String username);
}
@Service
public class UserService implements IUserService{
       // keep it as is
}