Как обеспечить безопасный api REST вместе с сеансом springboot и безопасностью spring без аутентификации

#spring-session #spring-security-rest

Вопрос:

Проблема: Мое приложение java springboot получает токен JWT от внешней системы для аутентификации пользователя с помощью внешнего поставщика управления идентификацией, который возвращает сведения о пользователе при успешном выполнении. После получения сведений о пользователях серверное приложение должно создать URL-адрес перенаправления для конечного пользователя внешней системы. URL-адрес перенаправления приведет пользователя в мое приложение angular, чтобы показать целевую страницу. Здесь все остальные API должны быть разрешены через сеанс http. В случае, если пользователь попытается получить прямой доступ к API rest, он должен получить сообщение об ошибке аутентификации.

Как мы можем добиться авторизации в этом случае, поскольку аутентификация не была выполнена моим приложением spring boot. Можем ли мы создать пользовательский весенний сеанс с помощью spring security и вручную поместить учетные записи пользователей в контекст безопасности?

Ответ №1:

В настоящее время я занимаюсь токенами JWT, полученными от Google. Включая Google, почти все серверы авторизации предоставляют API-интерфейсы rest , такие как GET /userInfo , где вы можете указать токен JWT в заголовке запроса или в URL-адресе в качестве параметра GET, а затем проверить, является ли токен JWT действительным, не истекшим и т. Д.

Поскольку проверка токена JWT обычно не имеет состояния, эти API, как правило, имеют большой лимит, и вы можете вызывать их столько раз, сколько вам нужно.

Я предполагаю, что у вас интегрирована система безопасности Spring, а затем вы можете добавить фильтр. Таким образом, каждый запрос должен быть проверен на наличие его маркера в заголовке.

 
@Service
public class TokenAuthenticationFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        try {
       String header = request.getHeader("Authorization");
            RestTemplate restTemplate = new RestTemplate(); // If you use Google SDK, xxx SDK, you do not have to use restTemplate 
            String userInfoUrl = "https://example.com/api/userInfo";

            HttpHeaders headers = new HttpHeaders();
            headers.set("Authorization", header);

            HttpEntity entity = new HttpEntity(headers);

            ResponseEntity<String> response = restTemplate.exchange(
                    userInfoUrl, HttpMethod.GET, entity, String.class, param);

            User user = response.getBody(); // Get your response and figure out if the Token is valid.

             // If the token is valid? Check it here....

                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(user, null, user.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);
    }
}