Spring boot Spring Boot JWT令牌基于角色的授权问题
所以,我试图实现的是使用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
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
}