使用gitee搭建图床,并解决防盗链问题

news2024/11/15 15:43:17

使用gitee搭建图床,并解决防盗链问题

一、搭建图床(图床—般是指储存图片的服务器)

1、有gitee账号,并搭建一个gitee仓库

点击新建仓库:

在这里插入图片描述

填写信息:

在这里插入图片描述

新建完就是这个模样了,点击管理:

在这里插入图片描述

把仓库弄成共有的这样大家都可以访问,也就是说你的网站可以不用登录你的gitee账号就可以查看你仓库里面的图片:

在这里插入图片描述

设置秘钥:

在这里插入图片描述

生成新令牌:记住,保存好,如果忘了,只能再生成一个令牌了

在这里插入图片描述

提交:

在这里插入图片描述

2、我们了解一下怎么上传图片Gitee API 文档,先不深究,熟悉一下,等会看代码

在这里插入图片描述

个人Gitee访问路径:我的就是i-dont-recognize-you,可以在设置—>个人资料—>个人空间地址中修改、查看

在这里插入图片描述

文件路径:可带文件夹,可以不创建,会自动创建,如:/img/blue.png 如果img这个文件夹不存在就新建这个文件夹并存入blue.png这个图片,如果存在,就直接找到这个文件夹,在里面存入blue.png这个图片。

3、代码编写

导入hutool的工具包

<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.5.8</version>
</dependency>

配置类(GiteeImgBed)

package bjwl.jk.zg.limsser.util;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 配置码云图床
 */
public class GiteeImgBed {
    public static String getNowDate() {
        Date now = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
        return formatter.format(now);
    }

    //码云私人令牌,需要补充
    public static final String ACCESS_TOKEN = "";
    //个人空间名,需要补充
    public static final String OWNER = "";
    //仓库名,需要补充
    public static final String REPO_NAME = "";
    //文件夹路径
    public static final String PATH = "/img/" + getNowDate() + "/";
    //message消息
    public static final String ADD_MESSAGE = "add img";
    public static final String DEl_MESSAGE = "del img";

    /**
     * 新建文件请求路径
     * <p>
     * owner*   仓库所属空间地址(企业、组织或个人的地址path)
     * repo*    仓库路径
     * path*    文件的路径
     * content* 文件内容, 要用 base64 编码
     * message* 提交信息
     * <p>
     * %s =>仓库所属空间地址(企业、组织或个人的地址path)  (owner)
     * %s => 仓库路径(repo)
     * %s => 文件的路径(path)
     */
    public static String CREATE_REPOS_URL = "https://gitee.com/api/v5/repos/%s/%s/contents/%s";
    /**
     * 获取路径下所有的内容
     * <p>
     * owner*   仓库所属空间地址(企业、组织或个人的地址path)
     * repo*    仓库路径
     * path*    文件的路径
     * content* 文件内容, 要用 base64 编码
     * message* 提交信息
     * <p>
     * %s =>仓库所属空间地址(企业、组织或个人的地址path)  (owner)
     * %s => 仓库路径(repo)
     * %s => 文件的路径(path)
     */
    public static String GET_IMG_URL = "https://gitee.com/api/v5/repos/%s/%s/contents/%s";

    /**
     * 删除文件请求路径
     * <p>
     * owner*   仓库所属空间地址(企业、组织或个人的地址path)
     * repo*    仓库路径
     * path*    文件的路径
     * content* 文件内容, 要用 base64 编码
     * message* 提交信息
     * <p>
     * %s =>仓库所属空间地址(企业、组织或个人的地址path)  (owner)
     * %s => 仓库路径(repo)
     * %s => 文件的路径(path)
     */
    public static String DEL_IMG_URL = "https://gitee.com/api/v5/repos/%s/%s/contents/%s";
}

控制器:我这里放了一个更新用户头像的逻辑代码,不需要删掉即可

package com.zhao.controller;

import cn.hutool.core.codec.Base64;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.zhao.common.R;
import com.zhao.pojo.User;
import com.zhao.service.IUserService;
import com.zhao.utils.GiteeImgBed;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 上传图床
 */
@RestController
@RequestMapping("/fix/img")
@Transactional(rollbackFor = Exception.class)
public class UploadController {
    @Autowired
    private IUserService userService;

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 上传图片
     * @param file
     * @return
     * @throws Exception
     */
    @PostMapping("uploadImg")
    public R uploadImg(@RequestParam("file") MultipartFile file,@RequestParam("userId") Integer userId) throws Exception {
        User user = new User();
        user.setUserId(userId);
        logger.info("请求成功");
        String originaFileName = file.getOriginalFilename();
        //上传图片不存在时
        if(originaFileName == null){
            return R.Failed("上传图片不存在");
        }
        String suffix = originaFileName.substring(originaFileName.lastIndexOf("."));
        //设置图片名字
        String fileName = System.currentTimeMillis() + "_" + UUID.randomUUID().toString() + suffix;

        String paramImgFile = Base64.encode(file.getBytes());
        //设置转存到Gitee仓库参数
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("access_token", GiteeImgBed.ACCESS_TOKEN);
        paramMap.put("message", GiteeImgBed.ADD_MESSAGE);
        paramMap.put("content", paramImgFile);

        //转存文件路径
        String targetDir = GiteeImgBed.PATH + fileName;
        //设置请求路径
        String requestUrl = String.format(GiteeImgBed.CREATE_REPOS_URL, GiteeImgBed.OWNER,
                GiteeImgBed.REPO_NAME, targetDir);
        logger.info("请求Gitee仓库路径:{}",requestUrl);

        String resultJson = HttpUtil.post(requestUrl, paramMap);
        JSONObject jsonObject = JSONUtil.parseObj(resultJson);
        //表示操作失败
        if (jsonObject==null || jsonObject.getObj("commit") == null) {
            return R.Failed("操作失败");
        }
        JSONObject content = JSONUtil.parseObj(jsonObject.getObj("content"));
        
        
        // 图片路径   这个路径记住后面要讲!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        String img = "https://gitee.com/i-dont-recognize-you/bishe-img/raw/master"+targetDir;
        //修改用户头像
        user.setImage(img);
        userService.updateById(user);
        return R.Success(requestUrl);
    }

    /**
     * 删除图片
     * @param imgPath
     * @return
     * @throws Exception
     */
    @DeleteMapping("/delImg")
    @ResponseBody
    public R delImg(@RequestParam(value = "imgPath") String imgPath) throws Exception {
        //路径不存在不存在时
        if(imgPath == null || "".equals(imgPath.trim())){
            return R.Failed("路径不存");
        }
        String path = imgPath.split("master/")[1];
        //上传图片不存在时
        if(path == null || "".equals(path.trim())){
            return R.Failed("上传图片不存在");
        }
        //设置请求路径
        String requestUrl = String.format(GiteeImgBed.GET_IMG_URL, GiteeImgBed.OWNER,
                GiteeImgBed.REPO_NAME, path);
        logger.info("请求Gitee仓库路径:{}",requestUrl);

        //获取图片所有信息
        String resultJson = HttpUtil.get(requestUrl);

        JSONObject jsonObject = JSONUtil.parseObj(resultJson);
        if (jsonObject == null) {
            logger.error("Gitee服务器未响应,message:{}",jsonObject);
            return R.Failed("Gitee服务器未响应");
        }
        //获取sha,用于删除图片
        String sha = jsonObject.getStr("sha");
        //设置删除请求参数
        Map<String,Object> paramMap = new HashMap<>();
        paramMap.put("access_token", GiteeImgBed.ACCESS_TOKEN);
        paramMap.put("sha", sha);
        paramMap.put("message", GiteeImgBed.DEl_MESSAGE);
        //设置删除路径
        requestUrl = String.format(GiteeImgBed.DEL_IMG_URL, GiteeImgBed.OWNER,
                GiteeImgBed.REPO_NAME, path);
        logger.info("请求Gitee仓库路径:{}",requestUrl);
        //删除文件请求路径
        resultJson = HttpRequest.delete(requestUrl).form(paramMap).execute().body();
        HttpRequest.put(requestUrl).form(paramMap).execute().body();
        jsonObject = JSONUtil.parseObj(resultJson);
		//请求之后的操作
        if(jsonObject.getObj("commit") == null){
            logger.error("Gitee服务器未响应,message:{}",jsonObject);
            return R.Failed("Gitee服务器未响应");
        }
        return R.Success("删除成功");
    }

}

JSON工具类:SpringBoot的JSON工具类(java),用于前后端分离_java自带json工具_我认不到你的博客-CSDN博客

4、查看图片:跟着点

在这里插入图片描述

在这里插入图片描述

此图我放最后,需要留着当壁纸的朋友自取

在这里插入图片描述

这个路径https://gitee.com/i-dont-recognize-you/bishe-img/raw/master跟后面图片的文件夹+文件名就是完整的URL地址

在这里插入图片描述

二、解决防盗链问题

1、要解决这个问题,我们先要知道这是什么,并且为什么需要解决这个问题

防盗链是什么?

防盗链不是一根链条,正确的停顿应该是防、盗链——防止其他网站盗用我的链接。

我把图片上传到gitee的服务器,得到了图片的链接,然后拿着这个链接在第三方编辑器中使用,这就是在“盗用”——因为这张图片占用了gitee的服务器资源,却为第三方编辑器工作,gitee得不到好处,还得多花钱。

如何实现防盗链?

要实现防盗链,就需要知道图片的请求是从哪里发出的。可以实现这一功能的有请求头中的originrefererorigin只有在XHR请求中才会带上,所以图片资源只能借助referer。其实gitee也确实是这么做的。

通过判断请求的referer,如果请求来源不是本站就返回302,重定向到gitee的logo上,最后在第三方网站引用存在gitee的资源就全变成它的logo了。

可以在开发者工具中看到第三方网站请求gitee图片的流程:

在这里插入图片描述

为什么需要解决这个问题?

1、我做毕设或者个人的作品时,我自己的服务器有点小,之前跑了几个服务就有点卡了,而且小编我也没几个钱,不想多买点服务器自己搭,才实习了几个月,白嫖才快乐呀

2、这样我们就可以用别人网站的图片了,岂不美哉,不用维护,gitee稳定,YYDS

解决方案:

1、打个广告,希望大佬们康康,留个小小的赞就行:搭建自己的文件服务器,小编这有两套搭建方案

springboot跨域上传文件(图片)到Linux远程服务器(本地操作也一样)把tomcat作为文件服务器_springboot上传图片到服务器_我认不到你的博客-CSDN博客

使用Docker搭建分布式文件存储系统MinIO_docker minio_我认不到你的博客-CSDN博客

2、使用Nginx做代理

嘿嘿,小编没用过,但所属麻烦了,如果大佬们感兴趣可以自己去搜搜

3、绕过防盗链的防护机制

三种情况下允许引用图片:

  1. 本网站。
  2. 无referer信息的情况。(服务器认为是从浏览器直接访问的图片URL,所以这种情况下能正常访问)
  3. 授权的网址。

上面讲述了3种可以拿到图片的方法,方法1和3能实现吗?肯定不行,所以我们只能从方法2入手了。

实施:

方法1:使用Vue或者html一样的方式

在html文件中加入<meta name="referrer" content="no-referrer">

在vue中的public文件夹下的index.html文件中

<!DOCTYPE html>
<html>
  <head>
      <!-- 就是这句 屏蔽掉referrer就可以了 -->
    <meta name="referrer" content="no-referrer">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="renderer" content="webkit">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title><%= webpackConfig.name %></title>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

方法2:

可以借助一个chrome小插件:ModHeader (如果你用的是Edge可以点这个链接直接获取),以下图这样设置一下就可以了

在这里插入图片描述

图片自取

在这里插入图片描述

参考文章:

Vue+Springboot使用Gitee图床上传图片_£漫步 云端彡的博客-CSDN博客_vue 图床 头像

你已经是个成熟的前端了,应该学会破解防盗链了 - 掘金 (juejin.cn)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/376495.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RFID射频卡写入手机NFC心路小记

声明&#xff1a; 本文仅是作者学习探索的心里路程日记&#xff0c;如果您看完以后&#xff0c;从中获得了一些知识&#xff0c;作者不胜荣幸。科技是一把双刃剑&#xff0c;利用好了&#xff0c;可以方便生活&#xff0c;利用不当也肯能扰乱公共管理秩序&#xff0c;造成不必要…

【软件测试】测试老鸟的迷途,进军高级自动化测试测试......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 很多从业几年的选手…

如何在没有任何额外包的情况下使用 NodeJS 下载文件

如何在没有任何额外包的情况下使用 NodeJS 下载文件 您可以下载文件&#xff08;图像、文本或任何类型的文件&#xff09;并使用 NodeJS 内置 https和 fs模块将其保存到您的文件系统。 该 https模块允许您使用 NodeJS 创建 HTTPS 请求&#xff0c;同时该 fs模块授予您访问文件…

VR全景的普及还将会带来什么新的风口?

5G技术的普及让VR全景在诸多行业中逐渐融合应用&#xff0c;VR全景展示可以更加真实、更加直观地让用户自主观看现场真实场景&#xff0c;基于身临其境的效果&#xff0c;VR全景展示已经被广泛的应用于各行各业&#xff0c;那么VR全景的普及还将会带来什么新的风口呢&#xff1…

FAST‘23《λ-IO: A Unified IO Stack for Computational Storage》论文解读

FAST’23《λ-IO: A Unified IO Stack for Computational Storage》论文解读 Data:2023-2-27 Ref: Z. Yang et al., “λ-IO: A Unified IO Stack for Computational Storage,” in 21st USENIX Conference on File and Storage Technologies (FAST 23), Santa Clara, CA, Feb.…

我的Android前沿技术—— Artifactory私服 搭建

我们说的私服&#xff0c;其实指的是企业局域网内的软件包依赖库。 说到软件库&#xff0c;就会牵扯出另一个概念——包管理器。 包管理器是在电脑中自动安装、配置、卸载和升级软件包的工具组合。包管理器由于其便捷性&#xff0c;被越来越多的新技术所采纳&#xff0c;从老…

Cesium 编程入门

Cesium 是什么&#xff1f; Cesium 是一个跨平台、跨浏览器的展示三维地球和地图的Javascript库。 Cesium 使用WebGL 来进行硬件加速图形&#xff0c;使用时不需要任何插件支持&#xff0c;但是浏览器必须支持WebGL。 Cesium能做什么&#xff1f; 支持2D、2.5D、3D形式的地图展…

Java代码规范

前言 由于近年来对于代码质量的要求越来越高&#xff0c;特制定部门级Java代码规范规则集X-JAVA-RULE&#xff0c;整体要求规则可用可查、循序渐进。 可用是指考虑目前已有代码的体量&#xff0c;不满足这些规则的代码能否能被修复&#xff0c;如果工作量巨大不能被修复或者实…

小程序和Vue+uniapp+unicloud培训课件

文章目录**一、什么是小程序****1.1** **小程序简介****1.2** **小程序的特点****1.3** **小程序的开发流程**个人小程序和企业小程序的区别1.4 小程序代码构成1.4.1 JSON 配置1.4.2 WXML 模板**数据绑定**逻辑语法条件逻辑列表渲染模板引用共同属性1.4.3 WXSS 样式1.4.4 JS 逻…

9. IP组播(理论)

作为IP传输三种方式之一&#xff0c;IP组播通信指的是IP报文从一个源发出&#xff0c;被转发到一组特定的接收者。相较于传统的单播和广播&#xff0c;IP组播可以有效地节约网络带宽、降低网络负载&#xff0c;所以被广泛应用于IPTV、实时数据传送和多媒体会议等网络业务中。 …

5 逻辑回归及Python实现

1 主要思想 分类就是分割数据&#xff1a; 两个条件属性&#xff1a;直线&#xff1b;三个条件属性&#xff1a;平面&#xff1b;更多条件属性&#xff1a;超平面。 使用数据&#xff1a; 5.1,3.5,0 4.9,3,0 4.7,3.2,0 4.6,3.1,0 5,3.6,0 5.4,3.9,0 . . . 6.2,2.9,1 5.1,2.5…

一个容易被忽视的标签 —— iframe

前言 甲问&#xff1a;说说你知道的HTML标签。 乙于是说了一大堆标签&#xff0c;比如div&#xff0c;span等等。 甲说&#xff1a;那你知道 iframe 标签吗&#xff1f; 乙这时候迟疑了片刻&#xff0c;缓缓说出&#xff1a;知道它&#xff0c;但是不太了解这个标签。 HTM…

学到了,原来华为是这样判断MES系统的好坏的

可以想象华为公司对供应商的要求是多么严格&#xff0c;那么我们今天来谈一下华为对供应商工厂MES系统这块的要求&#xff0c;这要从生产防错系统、品质管控系统、品质追溯系统、出货防错系统四个方面来说。一、生产物料和生产治具防错系统建立完整的物料和治具标签方案&#x…

常用的数据脱敏(手机、邮箱、身份证号)

一、什么是数据脱敏 先来看看什么是数据脱敏&#xff1f;数据脱敏也叫数据的去隐私化&#xff0c;在我们给定脱敏规则和策略的情况下&#xff0c;对敏感数据比如 手机号、银行卡号 等信息&#xff0c;进行转换或者修改的一种技术手段&#xff0c;防止敏感数据直接在不可靠的环境…

AcWing3485. 最大异或和

先看题目&#xff1a; 说实话&#xff0c;我看到这道题就想用滑动窗口&#xff0c;但是滑了一下发现不太对啊&#xff0c;如果我用滑动窗口的话&#xff0c;那么最后肯定是一个固定长度为m的窗口在持续计算&#xff0c;区间长度小于m的区间的异或和肯定会被遗漏。然后我就想怎么…

vue前端架构说明书模板示例

目录 1. 技术说明... 2 1.1 版本明细... 2 1.2 核心技术介绍... 2 2. 项目结构说明... 3 3. 自动化部署设置说明... 5 4. 打包及运行说明... 5 5. 导包说明... 6 5.1 方案一... 6 5.2 方案二... 7 5.3 补充说明... 7 6. 修改本地运行时链接的服务器说明... 7 7. 常…

从 B 站出发,用 Chrome devTools performance 分析页面如何渲染

页面是如何渲染的&#xff1f;通常会得到“解析 HTML、css 合成 Render Tree&#xff0c;就可以渲染了”的回答。但是具体都做了些什么&#xff0c;却很少有人细说&#xff0c;我们今天就从 Chrome 的性能工具开始&#xff0c;具体看看一个页面是如何进行渲染的&#xff0c;以及…

视频传输协议详解(RTMP、RTSP、HLS)

RTMP——Real Time Messaging Protocol&#xff08;实时消息传输协议&#xff09;RTMP是由Adobe公司提出的&#xff0c;在互联网TCP/IP五层体系结构中应用层&#xff0c;RTMP协议是基于TCP协议的&#xff0c;也就是说RTMP实际上是使用TCP作为传输协议。TCP协议在处在传输层&…

sql学习一

文章目录一、if 语句二、去重问题三、concat,upper,lower四、group_concat五、like 模糊匹配六、union和union all七、流程控制语句case八、limit一、if 语句 if(expr1, expr2, expr3)当expr1的值为真时函数的返回值为expr2&#xff0c;当expr1的值为假时&#xff0c;函数的返…

安装redis并设置开机自启动允许远程链接

一、进入/usr/local目录下面&#xff1b;下载redis包wget https://download.redis.io/releases/redis-5.0.14.tar.gz二、安装gccyum install gcc-c三、解压、进入目录、编译tar -xvf redis-5.0.14.tar.gzcd redis-5.0.14make ##如果报错zmalloc.h:50:31: 致命错误&#xff1a;j…