【问题标题】:Vaadin missing SpringSecurityContext in StreamResource callback methodVaadin 在 StreamResource 回调方法中缺少 SpringSecurityContext
【发布时间】:2019-08-12 02:17:41
【问题描述】:

我有一个简单的 StreamResource 示例,当单击下载锚点时,SpringSecurityContext 神秘地消失了。基本上,当单击下载锚点时,createInputStream 方法被调用以创建下载文件,但是当执行此方法时,SecurityContext 为空。下面是重现该问题的简化示例。

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

但我发现解决此问题的一种方法是在 createInputStream 方法中手动设置 SecurityContext。下面是一个例子。

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。

【问题讨论】:

    标签: java spring-boot spring-security vaadin vaadin-flow


    【解决方案1】:

    问题在于 Spring Security 的 WebSecurity 配置,下面的示例直接复制自 Vaadin 的 Bakery 应用示例。

    @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
    }
    

    问题是通过 StreamResource 或 Upload Component 动态创建的文件被映射到具有以下前缀 /VAADIN/dynamic/resource/** 的 url。在上面的配置中,我们用/VAADIN/** 告诉Spring Security 忽略所有以/VAADIN/ 开头的请求。这导致 Spring Security 忽略所有指向动态创建资源的 HttpServletRequest,因为 Vaadin 使用 /VAADIN/dynamic/resource/** url 前缀映射它们。当 Spring Security 忽略 HttpServletRequest 时,它的 SpringSecurityContext 将为空。请参阅WebSecurity.ignoring() 文档。

    可以通过将/VAADIN/** 重命名为/VAADIN/static/** 来解决此问题。这将防止 Spring Security 忽略对动态资源的请求,因此 SpringSecurityContext 将在 StreamResource 和 Upload 回调方法中可用。下面是一个工作示例。

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring()
           .antMatchers(
                   // Vaadin Flow static resources
                   "/VAADIN/static/**",
    
                   //Rest of configuration omitted for simplicity
    }
    

    【讨论】:

    • github 上的相应问题。
    猜你喜欢
    • 1970-01-01
    • 2021-12-08
    • 2019-01-26
    • 1970-01-01
    • 2012-11-24
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多