Vaadin falta SpringSecurityContext en el método de devolución de llamada StreamResource

Julius Koljonen:

Tengo un ejemplo sencillo donde StreamResource SpringSecurityContext desaparece misteriosamente cuando se hace clic en la descarga de anclaje. Básicamente, cuando se hace clic en descarga anclaje createInputStreammétodo es llamado para la creación de archivos de descarga, pero cuando se ejecuta este método SecurityContext es nulo. A continuación un ejemplo simplificado que reproduce el problema.

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());
}}

Cuando se ejecuta este código consigo los siguientes mensajes.

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

Pero descubrí que una manera de solucionar el problema es establecer la SecurityContext manualmente en el createInputStreammétodo. A continuación un ejemplo.

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());
}}

Al final llegué a esta pregunta. ¿Por qué es primavera SecurityContext perdió en el primer ejemplo es que hay una mejor manera de solucionar este problema o estoy atascado con el segundo ejemplo?

Como nota al margen Me di cuenta de que Subir componente de Vaadin está teniendo el mismo problema. SecurityContext se pierde en el addSucceededListenermétodo de devolución de llamada.

Estoy usando Vaadin 13.0.1 y la primavera de arranque 2.1.3.

Julius Koljonen:

El problema fue con la configuración de la primavera de Seguridad WebSecurity a continuación un ejemplo que es una copia directa de la aplicación de ejemplo panadería de Vaadin.

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring()
       .antMatchers(
               // Vaadin Flow static resources
               "/VAADIN/**", // This was the problematic spot

               //Rest of configuration omitted for simplicity
}

El problema era que los archivos creados de forma dinámica a través de StreamResource o Subir componente se asignan a una dirección URL que tiene un seguimiento de prefijo /VAADIN/dynamic/resource/**. En la configuración anterior le decimos a la primavera de Seguridad con /VAADIN/**al ignorar todas las solicitudes a partir de /VAADIN/. Esto lleva Spring Security para ignorar todas las HttpServletRequest ese punto a los recursos de forma dinámica creada desde Vaadin los mapea con /VAADIN/dynamic/resource/**url prefijo. Cuando la primavera de Seguridad ignora una HttpServletRequest que de SpringSecurityContext estará vacía. Ver WebSecurity.ignoring () documentación.

El problema se puede solucionar cambiando el nombre /VAADIN/**a /VAADIN/static/**. Esto evitará la primavera de Seguridad de ignorar los pedidos a los recursos dinámicos y por lo tanto SpringSecurityContext estará disponible en los métodos de devolución de llamada StreamResource y Subir. A continuación un ejemplo de trabajo.

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring()
       .antMatchers(
               // Vaadin Flow static resources
               "/VAADIN/static/**",

               //Rest of configuration omitted for simplicity
}

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=189684&siteId=1
Recomendado
Clasificación