Задать вопрос
@My1Name

Как защитить Spring приложение, отключив CSRF-токен?

Всем доброго времени суток.
Я пишу Spring-boot (security) приложение и хочу использовать все инструменты веб-разработки. А именно: iframe и упрощённые ajax запросы. Во время разработки отключаю CSRF, добавляя в настройки http.csrf().disable() По хорошему CORS запросы настраиваются, но в некоторых случаях настроек мало. Например, когда нужно сделать sharing через iframe (пример: YouTube, Twitter и др.). И я решаю эту задачу путём банального добавления Principal в параметры каждого контроллера.
@GetMapping("/page")
public @ResponseBody void page(Principal principal) {
if(principal==null)
return;
String email = principal.getName();
Person pers = service.getUserByLogin(email);
//some code....
}

Вся логика приложения строится на том, что каждый запрос либо авторизованный, либо нет. Разумеется, у каждого пользователя свои связные данные (Linked data) и он не может получить доступ к личной информации других пользователей. Вопрос: На сколько удовлетворяет такое решение Same Origin Policy и на сколько это безопасно?
  • Вопрос задан
  • 309 просмотров
Подписаться 2 Средний Комментировать
Пригласить эксперта
Ответы на вопрос 2
@My1Name Автор вопроса
Учитывая тот факт, что у меня не банковское приложение и финансовых рисков особо никаких нет, я не вижу причин запрещать пользователям встраивать личные страницы (или др. страницы сайта) в iframe. Главная задача в таком случае: ͟з͟а͟п͟р͟е͟т͟и͟т͟ь͟ ͟а͟в͟т͟о͟р͟и͟з͟и͟р͟о͟в͟а͟н͟н͟ы͟е͟ ͟з͟а͟п͟р͟о͟с͟ы͟. Для этого я разместил в шапку (в header на всех страницах сайта) незамысловатый скрипт:
const currentUrl = document.referrer;
$.get('ajax/index', {ref:currentUrl});

document.referrer - возвращает URL родительской страницы (которая загрузила iframe). Это работает, даже если родительский документ и iframe находятся на разных доменах. Как только начинается загрузка страницы, currentUrl отправляется в контроллер:
private @ResponseBody void checkReferrer(Principal principal, 
			HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		String currentUrl = req.getParameter("ref");
		currentUrl = currentUrl.substring(currentUrl.indexOf("/")+2);
		String localName = req.getServerName();
		if (principal!=null && !currentUrl.startsWith(localName)) {
			req.getSession().invalidate(); 
			req.logout();
			Cookie [] cookies = req.getCookies();
			if(cookies!=null) {
				for(Cookie c : cookies) {
					c.setValue("");
					c.setPath("/");
					c.setMaxAge(0);
					resp.addCookie(c);
				}
			}
		}
	}

Контроллер проверяет переданный URL и сравнивает его с именем сервера. Далее, если переданный адрес не включает в себя имя сервера и это ͟а͟в͟т͟о͟р͟и͟з͟и͟р͟о͟в͟а͟н͟н͟ы͟й͟ ͟з͟а͟п͟р͟о͟с͟, то происходит выход с системы и удаление всех куки. В настройках Spring-Security:
http.csrf()
.disable().and()
....
frameOptions().sameOrigin();

Политика Same-Origin предотвращает доступ внешним скриптам к странице встроенной в iframe. А при отключении скриптов, любые запросы будут происходить от имени пользователя. То есть, програмно можно получить доступ только к своему аккаунту и только через главный вход (через iframe вход не получится). А если я что-то не учёл - критика в комментариях приветствуется.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы