由Spring Security阻止的Spring MVC 4上传文件

时间:2016-05-12 02:37:27

标签: java spring hibernate spring-mvc spring-security

我正在通过Spring Form在Spring MVC 4项目中尝试上传文件,但是当我使用我的日志提交表单时说:Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@527de1e2Invalid CSRF token found

我从Spring Security Reference找到了解决方案 ,但是在Spring安全性之前放置Multipart Filter之后,我的Model Attrbute返回NULL。

这是我的代码:

JSP代码段

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>

<html>
<body>
<div>
    <form:form action="save?${_csrf.parameterName}=${_csrf.token}"
    method="post" modelAttribute="book" enctype="multipart/form-data">
        <table>
            <form:input type="hidden" path="id" />
            <tr>
                <td>ISBN:</td>
                <td><form:input path="isbn" autofocus="autofocus"/></td>
            </tr>
            <tr>
                <td>Title:</td>
                <td><form:input path="title" /></td>
            </tr>
            <tr>
                <td>Author:</td>
                <td><form:input path="author" /></td>
            </tr>
            <tr>
                <td>Publisher:</td>
                <td><form:input path="publisher" /></td>
            </tr>
            <tr>
                <td>Call Number:</td>
                <td><form:input path="callNumber" /></td>
            </tr>
            <tr>
                <td>Pages:</td>
                <td><form:input path="pages" /></td>
            </tr>
            <tr>
                <td>Pages:</td>
                <td><form:input path="imageFile" type="file" /></td>
            </tr>
            <tr>
                <td colspan="2" align="center">
                    <input type="submit" value="Save">
                </td>
            </tr>
        </table>
    </form:form>
</div>

   

模型

@Entity
@Table(name="books")
public class Book implements Serializable {

  private static final long serialVersionUID = 4235334951865878125L;

  @Id
  @Column(name = "id")
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private int id;

  @NotNull
  @NotEmpty
  @Size(min = 1, max = 25)
  @Column(name = "isbn")
  private String isbn;

  @NotNull
  @NotEmpty
  @Size(min = 1, max = 50)
  @Column(name = "title")
  private String title;

  @Size(max = 50)
  @Column(name = "author")
  private String author;

  @Size(max = 50)
  @Column(name = "publisher")
  private String publisher;

  @Size(max = 25)
  @Column(name = "call_number")
  private String callNumber;

  @Column(name = "pages")
  private int pages;

  @Column(name = "image_file")
  private byte[] imageFile;

  //Setter & Getter
}

Controller Snippet:

@RequestMapping(value = "/save", method = RequestMethod.POST)
@PreAuthorize("hasAnyAuthority('BOOK_ADD', 'BOOK_EDIT')")
public String saveBook(@ModelAttribute @Valid Book book, BindingResult result) {
    bookValidator.validate(book, result);

    if (result.hasErrors()) {
        return "book/form";
    }
    if (bookService.getBook(book.getId()) == null) {
        bookService.save(book);
    } else {
        bookService.update(book);
    }
    return "redirect:/book";
}

Servlet配置:

@Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver() {
    CommonsMultipartResolver resolver = new CommonsMultipartResolver();
    resolver.setDefaultEncoding("UTF-8");
    return resolver;
}

Spring Security Initializer:

@Override
protected void beforeSpringSecurityFilterChain(ServletContext servletContext) {
    insertFilters(servletContext, new MultipartFilter());
}

SQL表:

CREATE TABLE `books` (
  `id` INT(5) UNSIGNED NOT NULL AUTO_INCREMENT,
  `isbn` VARCHAR(25) NOT NULL,
  `title` VARCHAR(50) NOT NULL,
  `author` VARCHAR(50) NULL DEFAULT NULL,
  `publisher` VARCHAR(50) NULL DEFAULT NULL,
  `call_number` VARCHAR(25) NULL DEFAULT NULL,
  `pages` INT(5) NULL DEFAULT NULL,
  `image_file` MEDIUMBLOB NULL,
  PRIMARY KEY (`id`)
)

使用的库Snippet:

<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-webmvc</artifactId>
   <version>4.2.3.RELEASE</version>
</dependency>
<dependency.
   <groupId>org.springframework.security</groupId>
   <artifactId>spring-security-web</artifactId>
   <version>4.0.3.RELEASE</version>
</dependency>
<dependency>
   <groupId>org.springframework.security</groupId>
   <artifactId>spring-security-config</artifactId>
   <version>4.0.3.RELEASE</version>
</dependency>
<dependency>
   <groupId>commons-fileupload</groupId>
   <artifactId>commons-fileupload</artifactId>
   <version>1.3.1</version>
</dependency>
<dependency>
   <groupId>commons-io</groupId>
   <artifactId>commons-io</artifactId>
   <version>2.5</version>
</dependency>

3 个答案:

答案 0 :(得分:1)

您可以在Book类中添加新的MultipartFile属性,就像其他人建议的那样,并使其成为瞬态。设置此属性后,也可以设置imageFile。

@Column(name = "image_file")
private byte[] imageFile;

@Transient
private MultipartFile multiPartFile;

public void setMultiPartFile(MultipartFile multiPartFile) {
    this.multiPartFile = multiPartFile;
    if(multiPartFile != null){
        this.setImageFile(multiPartFile.getBytes());
    }
}

答案 1 :(得分:0)

通过更改

来尝试

private byte[] imageFile;

private MultipartFile imageFile;

<强>更新

如果在DB中使用blob数据类型,则从前端使用MultipartFile接收文件,然后使用byte []获得另一个getter setter。

private MultipartFile imageFileFrntEnd;
// getter
public MultipartFile setImageFileFrntEnd(MultipartFile file){
   //convert to byte[] and set to imageFile
}

private byte[] imageFile;
//getter setter

答案 2 :(得分:0)

Arip Hidayat,

我认为你需要编辑一些代码。

非常简单的java + spring mvc文件上传

config .xml

<!-- MultipartResolver -->
<bean id="multipartResolver"
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="-1" />
    <property name="maxInMemorySize" value="-1" />
</bean>

<!-- BeanNameViewResolver -->
<bean id="downloadViewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver">
    <property name="order">
        <value>0</value>
    </property>
</bean>

HTML

<form id="upload_form" action="/upload" method="POST" enctype="multipart/form-data">
     <label>file : </label> 
     <input type="file" name="file" id="file" /> 
     <input type="submit" value="upload" />
</form>

模型

public class MultipartFileModel {


private MultipartFile file;

//...getter, setter

}

这很重要。

输入标记名称=“文件”

模型MultipartFile变量名称=“文件”

控制器

    @RequestMapping(value = "/upload")
    private ModelAndView writeFile(MultipartFileModel model) {

        MultipartFile multipartfile = model.getFile();
        // you use "multipartfile"
        // ... you write file
}