解决 富文本 (ueditor) 图片或 视频 在spring boot中跨域问题

4 篇文章 0 订阅

1. 前言

1.1 什么是跨域

跨域指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。

出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)

1.1.1 跨域对比表

当前页面url被请求页面url是否跨域原因
http://www.test.com/http://www.test.com/index.html同源(协议、域名、端口号相同)
http://www.test.com/https://www.test.com/index.html跨域协议不同(http/https)
http://www.test.com/http://www.baidu.com/跨域主域名不同(test/baidu)
http://www.test.com/http://blog.test.com/跨域子域名不同(www/blog)
http://www.test.com:8080/http://www.test.com:7001/跨域端口号不同(8080/7001)

1.2 解决方案

  • JSONP (不推荐)

    # 通过<script> 标签的src属性不受同源策略方式 (只能使用GET请求)
    <script src="https://www.baidu.com/s?wd=百度百科" />
    
  • 代理服务器 (NGINX)

    <!-- 通过nginx的转发机制完成跨域 -->
    server {
            listen       80;
            server_name  b.b.com;
            location /Api {
     			# 反向代理
    		    proxy_pass  http://b.b.com:81/Api;
    			index  index.html index.htm;
            }
        }
    
  • cors

    通过服务端设置允许跨域的请求头

     response.setHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS");
                // 设置本次预请求的预检有效期 单位毫秒
                response.setHeader("Access-Control-Max-Age", "3600");
                // 指定该响应的资源是否被允许与给定的origin共享 * 允许所有域都具有访问资源的权限。
                response.setHeader("Access-Control-Allow-Origin", "*");
                // 设置本次预检请求允许正式请求中的设置的header
                response.setHeader("Access-Control-Allow-Headers",
                        "Content-Type, x-requested-with, X-Custom-Header, Authorization,access-control-allow-credentials,Access-Control-Allow-Methods," +
                                "X_Requested_With,Access-Control-Allow-Headers,Access-Control-Allow-Origin");
    

2. 解决ueditor上传附件跨域问题

2.1 前端

2.1.1 修改视频上传请求参数

路径: public\ueditor\dialogs\video\video.js

# 找到 uploadBeforeSend 定义的实现 
# 添加以下请求头: 
## header["Access-Control-Allow-Headers"] = "X-Requested-With";
## header["Access-Control-Allow-Methods"] = "POST,OPTIONS";
## header["Access-Control-Allow-Credentials"] = "true";
uploader.on('uploadBeforeSend', function (file, data, header) {
                //这里可以通过data对象添加POST参数
                header['X_Requested_With'] = 'XMLHttpRequest';
                header["Access-Control-Allow-Headers"] = "X-Requested-With";
                header["Access-Control-Allow-Methods"] = "GET,POST,OPTIONS";
                header["Access-Control-Allow-Credentials"] = "true";
                // HaoChuan9421
                if(editor.options.headers && Object.prototype.toString.apply(editor.options.headers) === "[object Object]"){
                    for(var key in editor.options.headers){
                        header[key] = editor.options.headers[key]
                    }
                }
            });

2.1.2 修改图片上传请求参数

路径: public\ueditor\dialogs\image\image.js

# 找到 uploadBeforeSend 定义的实现 
# 添加以下请求头: 
## header["Access-Control-Allow-Headers"] = "X-Requested-With";
## header["Access-Control-Allow-Methods"] = "POST,OPTIONS";
## header["Access-Control-Allow-Credentials"] = "true";
uploader.on('uploadBeforeSend', function (file, data, header) {
                //这里可以通过data对象添加POST参数
                header['X_Requested_With'] = 'XMLHttpRequest';
                header["Access-Control-Allow-Headers"] = "X-Requested-With";
                header["Access-Control-Allow-Methods"] = "PUT,POST,GET,DELETE,OPTIONS";
                header["Access-Control-Allow-Credentials"] = "true";
                // HaoChuan9421
                if(editor.options.headers && Object.prototype.toString.apply(editor.options.headers) === "[object Object]"){
                    for(var key in editor.options.headers){
                        header[key] = editor.options.headers[key]
                    }
                }
            });

2.2 后端

2.2.1 设置允许options请求方法

vim application.properties

# 允许options请求方法
spring.mvc.dispatch-options-request=true

2.2.2 添加过滤器


/**
 * @description: 解决跨域问题过滤器
 * @author: liqr
 * @create Date: 2020/11/28 16:07
 * @modify User:
 * @modify Date:
 * @modify Description:
 */
@Component
public class CorsFilter implements Filter {
    /**
     * options请求方法
     */
    final String OPTIONS_METHODS = "OPTIONS";

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        // 如果是options嗅探方法则直接设置响应头返回
        if (Objects.equals(((HttpServletRequest) req).getMethod(), OPTIONS_METHODS)) {
            HttpServletResponse response = (HttpServletResponse) res;
            // 设置本次预检请求的应答中明确了客户端所要访问的资源允许使用的方法或方法列表。
            response.setHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS");
            // 设置本次预请求的预检有效期 单位毫秒
            response.setHeader("Access-Control-Max-Age", "3600");
            // 指定该响应的资源是否被允许与给定的origin共享 * 允许所有域都具有访问资源的权限。
            response.setHeader("Access-Control-Allow-Origin", "*");
            // 设置本次预检请求允许正式请求中的设置的header
            response.setHeader("Access-Control-Allow-Headers",
                    "Content-Type, x-requested-with, X-Custom-Header, Authorization,access-control-allow-credentials,Access-Control-Allow-Methods," +
                            "X_Requested_With,Access-Control-Allow-Headers,Access-Control-Allow-Origin");
            return;
        }
        chain.doFilter(req, res);
    }
}

3. cors 扩展

3.1 cors 简介

​ 1. 整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

​ 2. 要实现CORS通信, 服务器端 必须实现CORS接口。

3.2 cors分类

​ cors请求又分为以下两类:

3.2.1 简单请求 (simple request)

  • 允许得请求方法
    • HEAD
    • GET
    • POST
  • 允许得头部信息
    • Accept
    • Accept-Language
    • Content-Language
    • Last-Event-ID
    • Content-Type:只限于三个值application/x-www-form-urlencodedmultipart/form-datatext/plain

请求头描述:

  • Access-Control-Request-Method

    • Access-Control-Request-Method : access-control-allow-methods,x_requested_with
      表明浏览在发送cors请求时 会使用到的方法列表(如: POST,GET)
      
  • Access-Control-Request-Headers

    • Access-Control-Request-Headers : POST
      表明浏览在发送cors请求时 会使用到的请求头列表 (如: x_requested_with)
      

3.2.2 非简单请求 (not-so-simple request)

除了以上简单请求允许的方法以及允许的请求头以外的请求都属于非简单请求

如:

  • PUT
  • DELETE
  • 。。。

所有的自定义的请求头中字段都会让浏览器认为该次请求为 非简单请求

3.2.2.1 OPTIONS(预检请求) 定义

​ 当浏览器认为本次请求为 非简单请求 时, 会默认先发送一个OPTIONS (预检请求), 向服务端询问是否允许进行跨域请求。

3.2.2.2 预检请求的响应
  • Access-Control-Allow-Headers

    • "Access-Control-Allow-Headers": "Content-Type, x-requested-with, X-Custom-Header, Authorization,access-control-allow-credentials,Access-Control-Allow-Methods,X_Requested_With,Access-Control-Allow-Headers,Access-Control-Allow-Origin"
      设置本次预检请求允许正式请求中的设置的header
      
  • Access-Control-Allow-Methods

    • "Access-Control-Allow-Methods": "POST,GET,OPTIONS"
      设置本次预检请求的应答中明确了客户端所要访问的资源允许使用的方法或方法列表。
      
  • Access-Control-Allow-Origin

    • "Access-Control-Allow-Origin" : "*"
      指定该响应的资源是否被允许与给定的origin共享 * 允许所有域都具有访问资源的权限。
      
  • Access-Control-Max-Age

    • "Access-Control-Max-Age" : "3600"
      设置本次预请求的预检有效期 单位毫秒
      
  • Access-Control-Allow-Credentials

    • 设置是否允许发送发送Cookie给服务端
      

3.3 请求示例

预检请求
在这里插入图片描述

正式请求
在这里插入图片描述

3.4 其他

  1. ​ 只要发送的 OPTIONS (预检请求) 服务端通过后, 后面的每次请求都会转成 简单请求 (simple request)
    ntials**
  • 设置是否允许发送发送Cookie给服务端
    

3.4 其他

  1. ​ 只要发送的 OPTIONS (预检请求) 服务端通过后, 后面的每次请求都会转成 简单请求 (simple request)
  2. ​ 如果 OPTIONS 请求中返回的信息不包含CORS有关的头部字段, 则抛出异常, 该异常会被XMLHttpRequestonerror进行捕获。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring实现UEditor图片上传可以参考以下步骤: 1. 在前端Vue代码配置UEditor富文本编辑器,并对上传图片做出相关设置。 2. 在Spring后端代码编写图片上传的控制器,处理前端传递的图片文件信息。 3. 在Spring配置文件配置文件上传的相关参数。 下面是具体的实现方法: 1. 前端代码: 在Vue组件引入UEditor富文本编辑器,可以使用UEditor官网提供的Vue UEditor Wrapper组件。并在UEditor配置项设置上传图片的相关参数,如下所示: ``` <template> <div> <vue-ueditor-wrap v-model="content" :config="ueditorConfig" :z-index="100" ></vue-ueditor-wrap> </div> </template> <script> import VueUeditorWrap from 'vue-ueditor-wrap'; export default { components: { VueUeditorWrap }, data () { return { content: '', ueditorConfig: { UEDITOR_HOME_URL: '/static/UEditor/', serverUrl: '/api/upload', maximumWords: 50000, initialFrameWidth: '100%', initialFrameHeight: 500, autoHeightEnabled: false, autoFloatEnabled: false, toolbars: [ ['source', 'bold', 'italic', 'underline', 'strikethrough', 'removeformat', 'formatmatch', 'forecolor', 'backcolor', 'fontfamily', 'fontsize', 'justifyleft', 'justifycenter', 'justifyright', 'justifyjustify', 'touppercase', 'tolowercase', 'link', 'unlink', 'insertimage', 'emotion', 'scrawl', 'music', 'insertvideo', 'attachment', 'map', 'gmap', 'insertcode', 'template', 'background', 'date', 'time', 'spechars', 'searchreplace', 'inserttable', 'deletetable', 'insertparagraphbeforetable', 'insertrow', 'deleterow', 'insertcol', 'deletecol', 'mergecells', 'mergeright', 'mergedown', 'splittocells', 'splittorows', 'splittocols', 'charts' ] ] }, }; }, }; </script> ``` 在上述代码,通过`serverUrl`参数设置了上传图片的后端接口地址为`/api/upload`。 2. 后端控制器代码: 在Spring,可以通过编写一个控制器方法来实现UEditor上传图片的功能。具体代码如下: ``` @RequestMapping(value = "/api/upload", method = RequestMethod.POST) @ResponseBody public String uploadImage(HttpServletRequest request, HttpServletResponse response) throws Exception { request.setCharacterEncoding("utf-8"); response.setHeader("Content-Type", "text/html"); String rootPath = request.getSession().getServletContext().getRealPath("/"); String contextPath = request.getContextPath(); String basePath = rootPath + File.separator + "upload" + File.separator; String savePath = contextPath + "/upload/"; String[] fileType = {".gif", ".png", ".jpg", ".jpeg", ".bmp"}; String upfile = "upfile"; JSONObject result = new JSONObject(); MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; Iterator<String> iterator = multipartRequest.getFileNames(); while (iterator.hasNext()) { MultipartFile file = multipartRequest.getFile(iterator.next()); if (file != null) { String fileName = file.getOriginalFilename(); String fileExt = fileName.substring(fileName.lastIndexOf(".")).toLowerCase(); boolean isAllow = false; for (String ext : fileType) { if (ext.equals(fileExt)) { isAllow = true; break; } } if (!isAllow) { result.put("state", "不支持的文件类型!"); return result.toJSONString(); } String newFileName = UUID.randomUUID().toString() + fileExt; File uploadedFile = new File(basePath, newFileName); if (!uploadedFile.getParentFile().exists()) { uploadedFile.getParentFile().mkdirs(); } file.transferTo(uploadedFile); result.put("state", "SUCCESS"); result.put("url", savePath + newFileName); result.put("title", newFileName); result.put("original", fileName); result.put("type", fileExt); result.put("size", file.getSize()); } } return result.toJSONString(); } ``` 3. Spring配置文件: 在Spring的配置文件,需要配置文件上传的相关参数。具体代码如下: ``` <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize" value="10485760"/> <property name="defaultEncoding" value="UTF-8"/> <property name="resolveLazily" value="true"/> </bean> ``` 其,`maxUploadSize`参数设置了上传文件的最大大小,单位为字节。 至此,我们就完成了在Spring+Vue实现UEditor图片上传的方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值