Spring Security не создает токен CSRF - PullRequest
0 голосов
/ 27 февраля 2019

Я хочу использовать Spring Security (версия 5.1.2) для генерации токена CSRF для моего приложения Angular 7.В моем файле SecurityConfig есть следующее:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.cors().and()
            .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}

со следующим RequestMapping в моем контроллере:

@RestController
@RequestMapping("/authentication")
public class AuthenticationController {

    @GetMapping("/csrf")
    public void getCsrfToken(){...}

    @PostMapping("/register")
    public RegisterOutputDTO register(@RequestBody UserDTO input){...}
}

Я получил из различных источников, что csrfTokenRepository автоматически сгенерирует cookieс заголовком XSRF-token при первом вызове GET (для этого /authentication/csrf), но я не получаю cookie-файл с сервера.Следовательно, при моем следующем POST звонке я получаю ответ 403.Что я мог упустить?

This is my output

1 Ответ

0 голосов
/ 28 февраля 2019

Как указано в комментариях к моему вопросу, я нашел ответ на свою проблему. Файл cookie не может быть отправлен между доменами.

Мой интерфейс был развернут на localhost:3000, а мой бэкэнд - на localhost:9080, которые, очевидно, считаются разными доменами.Если я перехожу на localhost:9080 (я получаю белую страницу, но это не имеет значения), а затем я перехожу на вкладку приложения в Chrome, я обнаруживаю, что файл cookie XSRF, который я искал, хранится так, как я ожидал все время,Файл cookie был доступен по номеру GET, который я выполнил из моего интерфейса.Проблема заключается в том, что файл cookie должен быть доступен для localhost:3000, чтобы Angular мог использовать файл cookie.

Существует несколько способов решения этой проблемы в вашей локальной среде.

Использование прокси

Вы можете использовать прокси для сопоставления определенных путей URL с вашим бэкэндом.Это решение, с которым я столкнулся.

Я запускаю свое приложение Angular на сервере веб-пакетов.Webpack предоставляет простой способ передачи определенных URL-адресов на ваш бэкэнд.Например:

devServer: {
    contentBase: path.join(__dirname, 'dist'),
    compress: true,
    port: 3000,
    proxy: {
        '/api': 'http://localhost:9080'
    }
}

Приложение Angular работает на localhost:3000.Любые звонки на localhost:3000/api/*.будет перенаправлен на localhost:9080/api/*.Так что в моем случае я больше не выполняю GET вызов на localhost:9080/api/authentication/csrf, но я звоню localhost:3000/api/authentication/csrf, который затем будет перенаправлен на мой бэкэнд.(Я добавил /api к пути в моем контроллере отдыха, для тех, кто интересуется.)

Развертывание обоих приложений на одном и том же порту

Использование frontend-maven-plugin вы можете создать внешний интерфейс в его папке dist, а затем позволить maven упаковать папку dist вместе с бэкендом для развертывания.Я не пробовал это, но есть различные ресурсы, которые показывают, что это должно быть легко сделать с загрузкой Spring.Таким образом, и внешний, и внутренний интерфейсы будут доступны, например, через localhost:9080.

Использование Spring Profile для локального отключения csrf

Вы можете использовать аннотации Spring @Profile, чтобы создать другую конфигурацию дляместная среда и отдых (тестирование, приемка, производство).Csrf может быть просто отключен для разработки.Я не предпочитаю эту опцию, так как мне нравится, чтобы DEV и другие среды были как можно больше.Это также не является реальным ответом на постановку проблемы.

Особая благодарность за ответ пользователя @dspies, который помог мне найти проблему.

...