В обратном вызове успешного запроса AJAX мне нужно добавить ссылку на модальное окно. Атрибут href ссылки указывает на маршрут API, который вызывает метод контроллера Spring Boot, который записывает PDF-файл, хранящийся на серверной стороне, в объект Response. Пользователь может щелкнуть ссылку, чтобы открыть новую вкладку, в которой отображается PDF-файл.
ЯС:
success: function (data) {
var fileId = data.id
$('#modalBody').append(`<a id = "viewFile" target = "_blank" href = "../api/getFile?fileId=${fileId}">View File</a>`)
}
Контроллер:
@RequestMapping(value = "api/getFile", method = RequestMethod.GET)
public void getFile(HttpServletResponse response, @RequestParam(value = "fileId") String fileId) {
Response fileResponse = fileService.getInputStream(fileId);
if (fileResponse == null) {
response.setStatus(500);
return;
}
InputStream is = response.body().byteStream();
response.addHeader(HttpHeaders.CONTENT_DISPOSITION, "inline;filename=sampleFile.pdf");
response.setContentType("application/pdf");
IOUtils.copy(is, response.getOutputStream);
response.setStatus(202);
response.flushBuffer();
is.close();
fileResponse.close();
}
Проблема в том, что инструмент сканирования уязвимостей помечает href как проблему XSS, поскольку я передаю непроверенные данные в качестве параметров запроса во внешний интерфейс. Есть ли другой способ открыть файл, полученный из серверной части, при нажатии на ссылку HTML?
Я попробовал использовать обработчик событий щелчка и установить для href маршрут по умолчанию, но он просто открывает текущую страницу вместо файла на новой вкладке. Есть ли у кого-нибудь предложения о том, как избежать передачи параметров запроса по маршруту href и как использовать onclick вместо href?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Эта уязвимость означает, что вам не следует отображать HTML без его предварительного экранирования.
Если вы использовали EJS или какой-либо другой шаблонизатор, он обычно экранирует HTML. Я использую эту функцию, esc_attr:
function esc_attr(string) {
if (!string) {
return "";
}
return ("" + string).replace(/[&<>"'/\\]/g, function(s) {
return {
"&": "&",
"<": "<",
">": ">",
'"': '"',
"'": ''',
"/": '/',
"\\": '\'
}[s];
});
}
// usage:
div.innerHTML = esc_attr("<scr"+"ipt>alert(13)</scr"+"ipt>");<div id = "div"></div>Или в вашем случае,
$('#modalBody').append(`<a id = "viewFile" target = "_blank" href = "../api/getFile?fileId=${esc_attr(fileId)}">View File</a>`)
На самом деле, поскольку вы используете его внутри URL-адреса, вам следует пойти дальше и также закодировать его для URL-адреса, используя encodeURIComponent.
Я считаю, что это лучшее сочетание:
$('#modalBody').append(`<a id = "viewFile" target = "_blank" href = "../api/getFile?fileId=${esc_attr(encodeURIComponent(fileId))}">View File</a>`)
это означает «совпадение» с регулярными выражениями в функции replace (документация), в данном случае один «злой» символ, который будет заменен его HTML-кодировкой.
ОБНОВЛЕНИЕ: я создал свой собственный метод проверки, который принимает строку URL-адреса, создает новую строку с теми же символами с нуля и возвращает эту новую чистую строку. Использование этого валидатора вместе с экранированными символами помогло мне решить проблему XSS. Большое спасибо!
Спасибо за подробный ответ! Можете ли вы объяснить, как работает оператор return и что означает
sв функцииesc_attrs()?