У меня есть простой пример StreamResource, где SpringSecurityContext таинственным образом исчезает при нажатии на ссылку для загрузки.Обычно при щелчке привязки загрузки createInputStream
вызывается метод для создания файла загрузки, но при выполнении этого метода SecurityContext имеет значение null.Ниже приведен упрощенный пример, который воспроизводит проблему.
public class HomeView extends VerticalLayout {
public HomeView() {
Anchor anchor = new Anchor();
anchor.add("DOWNLOAD");
anchor.setHref(new StreamResource("file", () -> createInputStream()));
add(anchor);
// SecurityContext returns correct value and is not null.
System.err.println(SecurityContextHolder.getContext());
System.err.println("Thread name in constructor : " + Thread.currentThread().getName());
}
private InputStream createInputStream() {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
outputStream.write("text".getBytes());
} catch (IOException e) {
e.printStackTrace();
}
// SecurityContextHolder.getContext() returns null here. Why?
System.err.println(SecurityContextHolder.getContext());
System.err.println("Thread name in createInputStream() : " + Thread.currentThread().getName());
return new ByteArrayInputStream(outputStream.toByteArray());
}}
Когда этот код выполняется, я получаю следующие сообщения.
org.springframework.security.core.context.SecurityContextImpl@db426455: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@db426455: Principal: org.springframework.security.core.userdetails.User@983d0d8b...Rest omitted
Thread name in constructor : http-nio-8080-exec-4
org.springframework.security.core.context.SecurityContextImpl@ffffffff: Null authentication
Thread name in createInputStream() : http-nio-8080-exec-9
Но я обнаружил, что одним из способов решения этой проблемы являетсяустановите SecurityContext вручную в методе createInputStream
.Ниже приведен пример.
public class HomeView extends VerticalLayout {
SecurityContext context;
public HomeView() {
Anchor anchor = new Anchor();
anchor.add("DOWNLOAD");
anchor.setHref(new StreamResource("file", () -> createInputStream()));
add(anchor);
// Save Context to a variable
context = SecurityContextHolder.getContext();
System.err.println(SecurityContextHolder.getContext());
}
private InputStream createInputStream() {
// Set SecurityContext before accessing it.
SecurityContextHolder.setContext(context);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
outputStream.write("text".getBytes());
} catch (IOException e) {
e.printStackTrace();
}
// SecurityContextHolder.getContext() no longer returns null.
System.err.println(SecurityContextHolder.getContext());
return new ByteArrayInputStream(outputStream.toByteArray());
}}
В итоге я получил этот вопрос. Почему Spring SecurityContext потерян в первом примере, есть ли лучший способ исправить это или я застрял во втором примере?
В качестве примечания я понял, что компонент загрузки Vaadin имеетта же проблема.SecurityContext теряется в addSucceededListener
методе обратного вызова.
Я использую Vaadin 13.0.1 и Spring Boot 2.1.3.