spring security下fileupload上传文件被拦截

fileupload插件github网址
fileupload插件jQuery网站
spring mvc+fileupload例子

好了,从刚开始引入js文件的时候就入了坑:

<script src="js/jquery.1.9.1.min.js"></script>
<script src="js/jquery.fileupload.js"></script>
<script src="js/vendor/jquery.ui.widget.js"></script>
<script src="js/jquery.iframe-transport.js"></script>
<script src="bootstrap/js/bootstrap.min.js"></script>
<link href="bootstrap/css/bootstrap.css" type="text/css" rel="stylesheet" />

我引入的时候按照以上顺序!!后来发现直接找不到方法:

$('#file').fileupload();

才发现要按照以下顺序:

<script src="js/jquery.1.9.1.min.js"></script>
<script src="js/vendor/jquery.ui.widget.js"></script>
<script src="js/jquery.iframe-transport.js"></script>
<script src="js/jquery.fileupload.js"></script>
<script src="bootstrap/js/bootstrap.min.js"></script>
<link href="bootstrap/css/bootstrap.css" type="text/css" rel="stylesheet" />

把jquery.fileupload.js放在最后面,这样才能在里面引用到其他js文件。


那么在Security里要post数据,必须要有csrf的token,否则一定会有403拒绝访问的壁要碰的 ……
有三种方法:
1. 直接将multipartfilter置于springSecurityFilterChain之上,这样就上传文件的时候就会先被multipartfilter拦截,而不会受到security的保护:
重写此方法:

public class SecurityApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

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

在xml配置中确保MultipartFilter 被放在springSecurityFilterChain之前:

<filter>
    <filter-name>MultipartFilter</filter-name>
    <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
</filter>
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>MultipartFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

这样,简单粗暴的解决了(当时这样,谁都可将文件上传到服务器,被短暂的保存起来,只有被授权的用户才可以上传一个被应用处理的文件。在大多数情况下,这些暂时被保存的文件不会有太大的问题,因为框架会定期自动清理。)


2.将csrf的token作为url参数:

<html>
<head>
    <meta name="_csrf" content="${_csrf.token}"/>
    <!-- default header name is X-CSRF-TOKEN -->
    <meta name="_csrf_header" content="${_csrf.headerName}"/>
    <!-- ... -->
</head>
<!-- ... -->
<form action="./upload?${_csrf.parameterName}=${_csrf.token}" method="post" enctype="multipart/form-data">

但是这样就导致token泄露了。
如果放到hidden区域里:

<input type="hidden"
    name="${_csrf.parameterName}"
    value="${_csrf.token}"/>

可能因为commons-fileupload组件对request进行封装的时候对csrf的支持有问题,没有传递csrf值。所以被over掉了…….


  1. 用AjaxUpload上传:
var uploader = new AjaxUpload({
        url: '/file/upload',
        name: 'uploadfile',
        multipart: true,
        customHeaders: { '${_csrf.headerName}': '${_csrf.token}' },
        ...
        onComplete: function(filename, response) {
            ...
        },
        onError: function( filename, type, status, response ) {
            ...
        }
});

但是网上没有找到此插件…….pass掉


4.用fileupload插件:

$('#file').fileupload({
                    dataType: 'json',
                    add: function (e, data) {
                        data.context = $('<button/>').text('Upload')
                                .appendTo(document.body)
                                .click(function () {
                                    data.context = $('<p/>').text('Uploading...').replaceAll($(this));
                                    data.submit();
                                });
                    },
                    done: function (e, data) {
                        data.context.text('Upload finished.');
                    }
                });

但是在jquery.fileupload.js里找了好久,发现了一个方法:_initXHRData: function (options) 跟设置request headers有点关系。可是怎么讲csrf的header和token传进去呢?!后来想到我可以直接用ajaxSend先设置requestHeader不就行了!!!
解决Spring Security 表单上传文件CSRF失效的问题

$(document).ready(function() {
            var token = $("meta[name='_csrf']").attr("content");
            var header = $("meta[name='_csrf_header']").attr("content");
            $(document).ajaxSend(function(e, xhr, options) {
                xhr.setRequestHeader(header, token);
            });
            $('#file').fileupload({
                    dataType: 'json',
                    add: function (e, data) {
                        data.context = $('<button/>').text('Upload')
                                .appendTo(document.body)
                                .click(function () {
                                    data.context = $('<p/>').text('Uploading...').replaceAll($(this));
                                    data.submit();
                                });
                    },
                    done: function (e, data) {
                        data.context.text('Upload finished.');
                    }
                });
<body>
    <div>
        <input type="file" name="file" id="file" data-url="/upload" /><br/>
    </div>
</body>

就酱紫,折腾了半天文档,还是用这种方法解决了!!!
PS:如果用的是thymeleaf模板,注意用的是:th:content

<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta name="_csrf" th:content="${_csrf.token}"/>
    <!-- default header name is X-CSRF-TOKEN -->
    <meta name="_csrf_header" th:content="${_csrf.headerName}"/>
</head>

参考:stackoverflow上类似解决方法
stackoverflow另一个网址

另外付一个用JSP的Taglib解决方法

<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
    <form method="post" action="/do/something">
        <sec:csrfInput />
        Name:<br />
        <input type="text" name="name" />
        ...
    </form>
    还有一个:<sec:csrfMetaTags />方法。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以使用Spring Boot的Servlet API来获取文件的内容,代码示例如下: @RequestMapping(method = RequestMethod.POST, value = "/upload") public void handleFileUpload(@RequestParam("file") MultipartFile file) { byte[] bytes = file.getBytes(); // 处理文件内容 } ### 回答2: 在Spring Boot中编写文件上传功能可以通过以下步骤实现: 1. 在pom.xml文件中添加Spring Boot Web和Apache Commons FileUpload的依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> </dependency> ``` 2. 创建一个Controller,用于处理文件上传请求: ```java import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; @Controller public class FileUploadController { @PostMapping("/upload") public String upload(@RequestParam("file") MultipartFile file) { // 处理文件上传逻辑 if (!file.isEmpty()) { try { byte[] fileBytes = file.getBytes(); // 对文件内容进行处理 // 返回上传成功的消息 return "File uploaded successfully"; } catch (IOException e) { // 处理文件读取异常 return "File upload failed: " + e.getMessage(); } } else { // 文件为空 return "File upload failed: File is empty"; } } } ``` 3. 创建一个HTML页面用于上传文件: ```html <!DOCTYPE html> <html> <body> <form th:action="@{/upload}" method="post" enctype="multipart/form-data"> <input type="file" name="file" /><br><br> <input type="submit" value="Upload" /> </form> </body> </html> ``` 通过以上步骤,你就可以在Spring Boot中实现文件上传并获取文件内容。在Controller中的`upload`方法中,我们使用`@RequestParam("file") MultipartFile file`来获取上传的文件,然后可以通过调用`file.getBytes()`获取文件的字节内容。你可以根据你的需求继续处理文件内容。 ### 回答3: 编写Spring Boot的文件上传功能,可以通过以下步骤来获取文件内容: 1. 首先,在Spring Boot应用程序的pom.xml文件中添加以下依赖项,以使用Spring Boot的文件上传功能: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web-services</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> ``` 2. 创建一个控制器类,用于处理文件上传请求和获取文件内容。可以使用`@RestController`注解来标记控制器类,并使用`@RequestMapping`注解来指定处理请求的URL路径。 ```java import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @RestController @RequestMapping("/upload") public class FileUploadController { @PostMapping public String uploadFile(@RequestParam("file") MultipartFile file) throws IOException { // 获取文件内容 byte[] fileContent = file.getBytes(); // 执行其他操作,例如保存文件内容到数据库中 return "File uploaded successfully!"; } } ``` 3. 在应用程序的配置文件(例如application.properties)中配置文件上传的相关属性: ```properties # 设置最大文件上传大小 spring.servlet.multipart.max-file-size=10MB spring.servlet.multipart.max-request-size=10MB ``` 4. 启动Spring Boot应用程序,并使用Postman或其他HTTP客户端发送一个POST请求到`/upload`路径,同时携带一个名为`file`的文件参数。 通过以上步骤,就可以在Spring Boot中编写一个文件上传功能,并获取上传文件的内容。在`uploadFile`方法中,通过`@RequestParam("file")`注解将上传的文件参数与MultipartFile对象绑定,然后使用`getBytes`方法获取文件内容的字节数组,可以根据需要进一步处理文件内容,例如保存到数据库中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值