加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java-Vaadin StreamResource回调方法中缺少SpringSecurityContex

发布时间:2020-12-14 19:26:45 所属栏目:Java 来源:网络整理
导读:我有一个简单的StreamResource示例,其中单击下载锚点时,SpringSecurityContext神秘地消失了.基本上,当单击下载锚点时,将调用createInputStream方法来创建下载文件,但是执行此方法时,SecurityContext为null.下面是重现该问题的简化示例. public class HomeVie

我有一个简单的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

但是我发现解决此问题的一种方法是在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的Upload组件也有同样的问题. SecurityContext在addSucceededListener回调方法中丢失.

我正在使用Vaadin 13.0.1和Spring Boot 2.1.3.

最佳答案
问题出在示例下方的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
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读