使用带有vaadin

时间:2017-07-24 19:48:09

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

在使用spring-boot的vaadin项目中使用spring security时遇到问题。所以我使用PdfViewer Addon来显示PDF文件。但是我收到以下错误消息:

error:"Not Found"
message:"No message available"
path:"/APP/PUBLISHED/pdf.worker.js"
status:404

我的spring安全配置如下所示:

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .headers()
                .defaultsDisabled()
                .frameOptions().sameOrigin().and()
                .csrf().disable() // Use Vaadin's CSRF protection
                .authorizeRequests().antMatchers("/").permitAll()
                .antMatchers("/vaadinServlet/HEARTBEAT/**").permitAll()
                .antMatchers("/vaadinServlet/UIDL/**").permitAll()
                .antMatchers("/vaadinServlet/APP/PUBLISHED/**").permitAll()
                .antMatchers("login?debug").permitAll()
                .antMatchers("/#!pwdreset/*").permitAll()
                .antMatchers("/pwdreset/*").permitAll()
                .and()
                .authorizeRequests()
                .and()
                .formLogin().loginPage("/#!login").permitAll()
                .and()
                .logout().logoutUrl("/#!login?logout").logoutSuccessUrl("/").permitAll().and()
                .sessionManagement().sessionFixation().newSession();

    }

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

因此,检查Chrome中已加载的文件我看到了一个文件夹 / vaadinServlet / APP / PUBLISHED / ,并且需要所有文件。

使用没有Spring Security的Addon工作正常,所以任何人都有任何想法吗?

更新

它似乎与spring安全性无关,因为我在一个新的简单项目中测试Addon时会遇到类似的行为。这似乎是春季靴子的问题。

要重现此问题,您需要(full project for download):

  • 基本春季启动+ vaadin应用程序骨架
  • 简单PDF并在/webapp/files
  • 下 您的pom和widgetset中的
  • PdfViewer add-on已编译
  • 以下简单的用户界面
@Theme("mytheme")
@SpringUI
@Widgetset("org.test.AppWidgetSet")
public class MyUI extends UI {
    @Override
    protected void init(VaadinRequest vaadinRequest) {
        final VerticalLayout layout = new VerticalLayout();
        String basepath = VaadinService.getCurrent().getBaseDirectory().getAbsolutePath();
        File file = new File(basepath.concat("/files/test.pdf"));
        if (file.exists()) {
            PdfViewer pdfViewer = new PdfViewer(file);
            Label info = new Label("File was found!");
            layout.addComponents(info, pdfViewer);
        } else {
            Label info = new Label("no file found!");
            layout.addComponent(info);
        }
        setContent(layout);
    }
}
  • open chrome&选择了Network标签的开发者工具,访问该应用,您应该会看到pdf.worker.js的一个请求失败。

1 个答案:

答案 0 :(得分:5)

TL; DR; 版本:

pdf.js正在触发第二个请求以下载pdf.worker.js,但它与自动配置的/vaadinServlet/APP/PUBLISHED/pdf.worker.js处理的路径VaadinServlet不匹配,只是{ {1}}。

我能提出的最简单的解决方案是/APP/PUBLISHED/pdf.worker.jsVaadinServlet的请求的控制器:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class PdfJsRedirectController {
    private static final String WORKER_JS_INCORRECT_PATH = "/APP/PUBLISHED/pdf.worker.js";
    private static final String WORKER_JS_CORRECT_FORWARD_PATH = "forward:/vaadinServlet/APP/PUBLISHED/pdf.worker.js";

    @RequestMapping(value = WORKER_JS_INCORRECT_PATH)
    public String forwardWorkerJsRequestToVaadin() {
        return WORKER_JS_CORRECT_FORWARD_PATH;
    }
}

详细版本:

所以,我花了一些时间来调试这个,结果发现这是一个不幸的配置组合:

  • spring dispatcher servlet listening
  • vaadin spring servlet listening
  • pdf.js bugfix / woraround

发生的情况是,spring为DispatcherServlet注册了/*个服务请求。和Vaadin为VaadinSpringServlet/vaadinServlet/*注册/VAADIN ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] ServletRegistrationBean : Mapping servlet: 'springVaadinServlet' to [/vaadinServlet/*, /VAADIN/*] 路径:

UI

为了与调度程序servlet共存并且能够在“/ *”上提供请求,Vaadin还为/MyUI路径注册转发控制器。例如,/vaadinServlet/MyUI上的请求将转发至js(有关详情,请参阅forwards)。

到目前为止一切正常,你不应该有任何问题。就像你说的那样,查看chrome dev-tools所有pdf.worker.js文件都在那里,那有什么不对?如果你看到访问你的应用程序时提出的请求,你会注意到实际上有2个Initiator请求 - 第一个成功的请求,以及给你404的请求:

VaadinServletConfiguration sources

失败的调用的workerSrc=/APP/PUBLISHED/pdf.worker.js列实际上是pdf.worker.js requests,如果设置了断点,您实际上可以看到public native void loadResourcePdf(String fileName, VPdfViewer instance)/*-{ var pdfviewer = instance.@pl.pdfviewer.client.ui.VPdfViewer::jsObject; pdfviewer.work = false; if ((pdfviewer.fileName == null || pdfviewer.fileName != fileName) && fileName != null) { $wnd.PDFJS.disableStream = true; ======> $wnd.PDFJS.workerSrc = 'APP/PUBLISHED/pdf.worker.js'; $wnd.PDFJS.getDocument(fileName).then(function (pdf) { pdfviewer.pdfFile = pdf; pdfviewer.fileName = fileName; pdfviewer.pageCount = pdf.numPages; if (pdfviewer.pageNumber == 0 && pdf.numPages > 0) { pdfviewer.pageNumber = 1; } pdfviewer.showPdfPage(pdfviewer.pageNumber); }); } }-*/; pdf.js:2344中定义的值}。您可能需要水平滚动一点才能看到代码,所以我在下面对它进行了格式化:

/APP/PUBLISHED/pdf.worker.js

pl.pdfviewer.client.ui.PdfViewer.java

在常规的Vaadin环境中,/APP/PUBLISHED/pdf.worker.js可以开箱即用,但我们现在处于略微改变的状态,因此我们需要进行一些调整。最重要的是,我们可以使用与Vaadin自动配置相似的方法,并将/vaadinServlet/APP/PUBLISHED/pdf.worker.js请求重定向到@Entity @ToString @EqualsAndHashCode public class Driver { public static final String COLUMN_CAR = "car"; @Id @GeneratedValue private long id; @Getter @Setter @OneToOne(cascade = CascadeType.ALL) @JoinColumn(name = COLUMN_CAR) private Car car; } ,最后克服了这个问题。为简洁起见,可以在本文开头看到重定向控制器。

js debug