spring 如何从控制器中的令牌获取用户的电子邮件?

ocebsuys  于 2023-04-19  发布在  Spring
关注(0)|答案(1)|浏览(98)

我是Spring Security的新手。我有一个JWT令牌过滤器,它检查所有请求的授权令牌是否有效。据我所知,如果令牌无效,请求将被取消并返回错误。

@Component
@RequiredArgsConstructor
public class JwtTokenFilter extends OncePerRequestFilter {
    private final JwtTokenProvider tokenProvider;
    private final UserDetailsService userDetailsService;

    @Override
    protected void doFilterInternal(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull FilterChain filterChain) throws ServletException, IOException {
        final String authHeader = request.getHeader("Authorization");
        final String token;
        final String email;

        if (authHeader == null || !authHeader.startsWith("Bearer ")){
            filterChain.doFilter(request, response);
            return;
        }

        token = authHeader.substring(7);
        email = tokenProvider.getUserEmail(token);
        if (email != null && SecurityContextHolder.getContext().getAuthentication() == null){

            // User is not yet authenticated (not connected)
            UserDetails user = this.userDetailsService.loadUserByUsername(email);
            if (tokenProvider.isTokenValid(token, user)){
                UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
                        user, null, user.getAuthorities()
                );
                authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(authToken);
            }

        }
        filterChain.doFilter(request, response);
    }

    public String getEmailFromHeader(String header){
        if (header == null || !header.startsWith("Bearer ")){
            throw new UserNotExistException();
        }

        String token = header.substring(7);
        String email = tokenProvider.getUserEmail(token);
        return email;
    }
}

我希望用户能够只通过自己的token从控制器接收一些数据。现在我在控制器中有一个方法,可以从头部检索token:

@GetMapping("/friends")
public ResponseEntity<Set<User>> getFriends(@RequestHeader(HttpHeaders.AUTHORIZATION) String header){
    String email = tokenFilter.getEmailFromHeader(header);
    User user = service.findByEmail(email);
    if (user == null){
        throw new UserNotExistException();
    }
    return ResponseEntity.ok(user.getFriends());
}

有没有什么方法可以避免从每个控制器的头中获取令牌?我如何在JWTTokenFilter中进行身份验证后立即获取用户的电子邮件?

vsikbqxv

vsikbqxv1#

如果用户通过了身份验证,则可以从安全上下文保持器获取用户信息
这是security,它将username设置为security context保持器:

@RequiredArgsConstructor
@Component
public class JwtFilter extends OncePerRequestFilter {
    private final AccessTokenUtil accessTokenUtil;
    private final UserService userService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String token = request.getHeader("Authorization");
        String email =null;
        if (token != null && token.startsWith("Bearer ")) {
            token = token.substring(7);
            try {
                email = accessTokenUtil.getEmailFromJwt(token);
            } catch (IllegalArgumentException e) {
                System.out.println("Not Valid");
            } catch (ExpiredJwtException e) {
                System.out.println("Expired JWT token");
            } catch (Exception e) {
                System.out.println("Something wrong");
            }
            if (email != null && accessTokenUtil.checkExpireDate(token) && SecurityContextHolder.getContext().getAuthentication() == null) {
                UserDetails userDetails = userService.loadUserByUsername(email);
                UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(email, null, userDetails.getAuthorities());
                SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            }
        }
        filterChain.doFilter(request,response);
    }
}

控制器:

@RestController
@RequiredArgsConstructor
public class UserController{

  private Users getCurrentUser() {
    String login = 
    SecurityContextHolder.getContext().getAuthentication().getName();
    if (login != null && !login.equals("anonymousUser")) {
        Optional<Users> optionalUsers = userRepo.findByEmail(login);
        return optionalUsers.orElse(null);
    }
    return null;
  }

}

getCurrentUser()方法返回currentUser,如果想获取username可以返回login,login是username

相关问题