简体   繁体   中英

Spring MVC 4 Upload File Blocked by Spring Security

Im trying upload file in my Spring MVC 4 project via Spring Form, but when I submit form with my log say : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@527de1e2 and Invalid CSRF token found .

And I found solution from Spring Security Reference , but After I placing Multipart Filter before Spring security, my Model Attrbute are returning NULL.

Here is my codes :

JSP Snippet :

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

Model

@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 Configuration :

@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 Table :

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`)
)

and Library Snippet Im Using :

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

You can add a new MultipartFile attribute in Book class like what other people suggest, and make it transient. When this attribute is set, and set your imageFile as well.

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

Try it by changing

private byte[] imageFile;

to

private MultipartFile imageFile;

Update

If you are using blob datatype in DB,you receive the file using MultipartFile from front end and then have another getter setter with byte[].

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

private byte[] imageFile;
//getter setter

Arip Hidayat,

I think you need to edit some code.

very simple java + spring mvc file upload

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>

Model

public class MultipartFileModel {


private MultipartFile file;

//...getter, setter

}

It is important.

input tag name = "file"

model MultipartFile variable name = "file"

Controller

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM