Spring Boot - проверка подлинности JWT без вызовов БД - PullRequest
0 голосов
/ 06 марта 2019

Можно ли реализовать простую аутентификацию JWT (не заботясь о аннулировании токенов - я сделаю это в кеше) без вызовов базы данных для загрузки пользователя в контекст безопасности? Я вижу, что моя текущая реализация попадает в базу данных при каждом вызове API (чтобы загрузить пользователя в контекст безопасности). Ниже вы можете увидеть часть реализации JwtAuthenticationFilter расширение OncePerRequestFilter :

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    try {
        String jwt = getJwtFromRequest(request);
        if (StringUtils.hasText(jwt) && tokenProvider.validateToken(jwt)) {
            Long userId = tokenProvider.getUserIdFromJWT(jwt);
            UserDetails userDetails = customUserDetailsService.loadUserById(userId);
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
    } catch (Exception ex) {
        logger.error("Could not set user authentication in security context", ex);
    }
    filterChain.doFilter(request, response);
}

А вот вызов базы данных, которого я хотел бы избежать (при каждом аутентифицированном вызове api):

@Service
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    UserRepository userRepository;

    // This method is used by JWTAuthenticationFilter
    @Transactional
    public UserDetails loadUserById(Long id) {
        User user = userRepository.findById(id).orElseThrow(
            () -> new UsernameNotFoundException("User not found with id : " + id)
        );
        return UserPrincipal.create(user);
    }
}

Я нашел какое-то решение проблемы для создания объекта UserPrincipal (он реализует UserDetails интерфейс) только с идентификатором пользователя , username и предоставлено власти и без пароль , который я не могу прочитать из самого токена JWT (остальное могу), но я не уверен, является ли он безопасным и считается ли это хорошим решением ( UserDetails класс требует поле пароля и его хранение JWT не было бы разумно, я думаю). Мне нужен экземпляр UserPrincipal (реализующий интерфейс UserDetails) для поддержки в качестве аргумента UsernamePasswordAuthenticationToken , как вы можете видеть в первом абзаце.

...