前端常用的几种加密方法

文章目录

  • 前端常用的几种加密方法
    • md5 加密(不可逆)
    • base64 位加密(可加密可解密)
    • RSA 加密(公钥加密,私钥解密)
    • AES 加密(需要密钥才能解密)
    • CryptoJS
    • 常用的加密方式--demo
  • ✒️总结


前端常用的几种加密方法

在这里插入图片描述

在信息安全越来越受重视的今天,JS 安全一直是前端工程师们注重的大问题,前端的各种加密也变得更加重要。通常跟服务器的交互中,为保障数据传输的安全性,避免被人抓包篡改数据,除了 https 的应用,还需要对传输数据进行加解密,保证了所有使用者的权益不被侵犯。

常见加密方式:

  • 对称加密算法(对称加密算法是指加密和解密使用相同密钥的加密算法。在前端常用的对称加密算法包括 AES、DES 等。对称加密算法的安全性依赖于密钥,泄露密钥就意味着任何人都可以对他们发送或接收的消息解密,所以密钥的保密性对通信的安全性至关重要。对称加密算法的优点在于算法公开、计算量小、加密速度快、加密效率高,缺点在于在数据传送前,发送方和接收方必须商定好密钥,然后双方保存好密钥。如果一方的密钥被泄露,那么加密信息也就不安全了。对称加密算法适用于本地数据加密、https 通信、网络传输等场景。)
  • Hash 算法(Hash 算法是一种将任意长度的数据转换成固定长度的哈希值的算法。在前端常用的 Hash 算法包括 MD5、SHA-1 等。Hash 算法是不可逆的,因此常用于验证数据的完整性,例如文件校验和、密码加密等。Hash 算法的优点在于可以将任意长度的数据转换成固定长度的哈希值,且计算速度快、效率高,缺点在于无法通过哈希值恢复原始数据。Hash 算法适用于数据完整性校验等场景。)
  • 非对称加密算法(非对称加密算法是指加密和解密使用不同密钥的加密算法,其中公钥用于加密,私钥用于解密。在前端常用的非对称加密算法包括 RSA 等。非对称加密算法的安全性依赖于公钥和私钥的生成和管理,泄露任何一把密钥都意味着任何人都可以对他们发送或接收的消息解密,所以公钥和私钥的保密性对通信的安全性至关重要。非对称加密算法的优点在于可以保证数据传输的安全性,缺点在于算法复杂、计算量大、加密速度慢、效率低。非对称加密算法适用于数字签名、身份认证等场景。)

md5 加密(不可逆)

MD5 是比较常见的 Hash 算法,对于 MD5 而言,有两个特性是很重要的,第一:明文数据经过散列以后的值是定长的;第二:是任意一段明文数据,经过散列以后,其结果必须永远是不变的。前者的意思是可能存在有两段明文散列以后得到相同的结果,后者的意思是如果我们散列特定的数据,得到的结果一定是相同的。
js-md5 加密方式 MD5 加密后的位数有两种:16 位与 32 位。默认使用 32 位。(16 位实际上是从 32 位字符串中取中间的第 9 位到第 24 位的部分)为提高安全性。根据业务需求,可以对 md5 添加偏移量。如对原有字符拼接指定位数的字符串

npm 安装

npm install --save js-md5

使用

// 然后在页面中 引入
import md5 from 'js-md5'
md5('加密内容') //默认32位
md5('加密内容').substring(8, 24) // 从第8个字符开始截取16位

base64 位加密(可加密可解密)

Base64 是用于网络上传输 8Bit 字节码的最常见的编码方法之一,Base64 不是安全领域的加密算法。实际上,Base64 只能算是一种编码算法,对数据内容进行编码以适应传输。Base64 是一种将二进制数据转换为 ASCII 字符串的编码方法。它将每 3 个字节的数据编码为 4 个可打印的 ASCII 字符,因此 Base64 编码后的数据长度总是原数据长度的约 4/3 倍(不足 4 的倍数时进行补位)。Base64 编码表由 64 个字符组成,其中包含大小写字母、数字和两个特殊字符 “+”, “/”,同时还有一个填充字符 “=”。Base64 编码是一种可逆操作,可以通过解码操作还原原始数据。

npm 安装

   npm install --save js-base64

使用

/**
 * BASE64加密
 * @param str
 * @returns {string}
 */
base64Encode(str) {
  return btoa(unescape(encodeURIComponent(str)))
}
/**
 * BASE64解密
 * @param str
 * @returns {string}
 */
base64Decode(str) {
  return decodeURIComponent(escape(atob(str)))
}

RSA 加密(公钥加密,私钥解密)

RSA 加密:RSA 是一种非对称加密算法,它使用公钥和私钥进行加密和解密。在前端使用 RSA 加密时,需要使用第三方库进行加密和解密操作,例如 jsencrypt。RSA 加密适用于加密大量数据或进行数字签名等场景。

// 使用公钥加密
var publicKey = 'public_key_123'
var encrypt = new JSEncrypt()
encrypt.setPublicKey(publicKey)
var encrypted = encrypt.encrypt('Hello World')

// 使用私钥解密
var privateKey = 'private_key_123'
var decrypt = new JSEncrypt()
decrypt.setPrivateKey(privateKey)
var uncrypted = decrypt.decrypt(encrypted)

AES 加密(需要密钥才能解密)

AES 加密:AES 是一种对称加密算法,它使用相同的密钥进行加密和解密。在前端使用 AES 加密时,需要使用第三方库进行加密和解密操作,例如 crypto-js。AES 加密适用于加密大量数据或进行对称加密等场景。

var CryptoJS = require('crypto-js')
var data = { id: 1, text: 'Hello World' }
// 加密生成密文
var ciphertext = CryptoJS.AES.encrypt(
  JSON.stringify(data),
  'secret_key_123'
).toString()
// 解密得到明文
var bytes = CryptoJS.AES.decrypt(ciphertext, 'secret_key_123')
var decryptedData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8))

CryptoJS

CryptoJS 是一个 JavaScript 的加解密的工具包。它支持多种算法:MD5、SHA1、SHA2、SHA3、RIPEMD-160 的哈希散列,以及进行 AES、DES、Rabbit、RC4、Triple DES 加解密。

npm 安装

npm install crypto-js

封装加密文件 asc.js

// 1.引入CryptoJS加密插件
import CryptoJS from 'crypto-js'

// 2.设置秘钥和偏移量需要和后端一致

// 十六位十六进制数作为密钥
const KEY = CryptoJS.enc.Utf8.parse('wtkjtobacco12345')
// 十六位十六进制数作为密钥偏移量
const IV = CryptoJS.enc.Utf8.parse('123456wtkj654321')

export default {
  /**
   * 加密方法
   * @param {*} word
   * @param {*} keyStr
   * @param {*} ivStr
   */
  encrypt(word, keyStr, ivStr) {
    let key = KEY
    let iv = IV
    if (keyStr) {
      key = CryptoJS.enc.Utf8.parse(keyStr)
      iv = CryptoJS.enc.Utf8.parse(ivStr)
    }
    let srcs = CryptoJS.enc.Utf8.parse(word)
    var encrypted = CryptoJS.AES.encrypt(srcs, key, {
      iv: iv,
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.ZeroPadding,
    })
    return CryptoJS.enc.Base64.stringify(encrypted.ciphertext)
  },

  /**
   * 解密方法
   * @param {*} word
   * @param {*} keyStr
   * @param {*} ivStr
   */
  decrypt(word, keyStr, ivStr) {
    let key = KEY
    let iv = IV

    if (keyStr) {
      key = CryptoJS.enc.Utf8.parse(keyStr)
      iv = CryptoJS.enc.Utf8.parse(ivStr)
    }

    let base64 = CryptoJS.enc.Base64.parse(word)
    let src = CryptoJS.enc.Base64.stringify(base64)

    let decrypt = CryptoJS.AES.decrypt(src, key, {
      iv: iv,
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.ZeroPadding,
    })

    let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8)
    return decryptedStr.toString()
  },
}

在登录组件 login.vue 使用

<template>
  <div class="home">
    <el-form
      :model="userForm"
      status-icon
      :rules="rules"
      ref="userForm"
      label-width="100px"
      class="demo-userForm"
      label-position="top"
    >
      <el-form-item prop="phone">
        <el-input
          type="text"
          v-model="userForm.phone"
          prefix-icon="el-icon-user"
          placeholder="请输入用户名"
        >
        </el-input>
      </el-form-item>
      <el-form-item prop="password" style="margin-top: 20px !important">
        <el-input
          type="password"
          v-model="userForm.password"
          show-password
          prefix-icon="el-icon-goods"
          placeholder="请输入密码"
        >
        </el-input>
      </el-form-item>
    </el-form>
    <el-button @click="submitForm('userForm')">登录</el-button>
  </div>
</template>
<script>
  import asc from "@/plugins/asc"; //引入封装好的加密
  export default{
    name:'login',
    data(){
      return{
        // 表单绑定数据
        userForm: {
          phone: "",
          password: "",
        },
        encryptionFrom: {}, //加密表单
        // 校验规则
        rules: {
          phone: [{ required: true, message: "账号不能为空!" }],
          password: [{ required: true, message: "密码不能为空!" }],
        },

      }
    }
    methods:{
      // 登录按钮事件
        submitForm(formName) {
        this.$refs[formName].validate((valid) => {
          // this.$router.push({ name: "tobaccoBureau" });
          if (valid) {
            this.loading = true;
            this.encryptionFrom = JSON.parse(JSON.stringify(this.userForm));
            // 加密
            this.encryptionFrom.password = asc.encrypt(this.userForm.password);
            this.$axios({
              url: `auth/login`,
              method: "POST",
              params: this.encryptionFrom,
            })
              .then(async (res) => {
                if (res.success) {

                  if (this.isRemenberPassword) {
                    // 判断是否勾选了记住密码
                    this.saveLocalPassword();
                  } else {
                    localStorage.removeItem("localPassword");
                  }
                  console.log("res", res);
                  sessionStorage.setItem("token", res.data.token);//存储token
                  await this.$store.dispatch("getUserInfo");
                  // this.$router.push({ name: "case" });
                  // this.$message.success("登录成功");
                }
              })
              .catch((err) => {})
              .finally(() => {
                this.loading = false;
              });
          }
        });
      },
    //保存缓存密码
    saveLocalPassword() {
      console.log("保存", this.form);
      localStorage.setItem("localPassword", JSON.stringify(this.form));
    },
    // 获取缓存密码
    getLocalPassword() {
      this.isRemenberPassword = false;
      let form = JSON.parse(localStorage.getItem("localPassword"));
      if (form) {
        this.isRemenberPassword = true;
        this.form = form;
      }
    },
    }
  }
</script>

常用的加密方式–demo

<template>
  <div class="main">
    <el-form :model="form" :rules="rules" ref="dialog_form" label-width="80px">
      <el-row>
        <el-col :span="6">
          <el-form-item label="密码:">
            <el-input
              placeholder="请输入"
              size="small"
              v-model="form.password"
              @change="passwordChange"
            ></el-input>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row
        >----------------------------------------------------------------------------------------------------------------</el-row
      >

      <el-row>
        <h1 class="title">md5加密(默认32位)</h1>
        <span>{{ md5Encode(form.password) }}</span>
      </el-row>
      <el-row>
        <h1 class="title">md5加密(16位)</h1>
        <span>{{ md5Encode2(form.password) }}</span>
      </el-row>
      <el-row>
        <span class="detail"
          >js-md5加密方式 MD5 加密后的位数有两种:16 位与 32 位。默认使用 32
          位。 (16 位实际上是从 32 位字符串中取中间的第 9 位到第 24
          位的部分)为提高安全性。根据业务需求,可以对 md5
          添加偏移量。如对原有字符拼接指定位数的字符串。</span
        >
      </el-row>
      <el-row>
        <h1 class="title">base64加密(方法1 window.btoa)</h1>
        <span>{{ base64Encode1(form.password) }}</span>
      </el-row>

      <el-row>
        <h1 class="title">base64加密(方法3 Base64.encode使用插件)</h1>
        <span>{{ base64Encode2(form.password) }}</span>
      </el-row>
      <el-row>
        <h1 class="title">
          base64加密(方法3 btoa(unescape(encodeURIComponent)))
        </h1>
        <span>{{ base64Encode3(form.password) }}</span>
      </el-row>
      <el-row>
        <h1 class="title">
          base64解密(方法3 decodeURIComponent(escape())使用插件)
        </h1>
        <span>{{ base64Decode(base64Encode3(form.password)) }}</span>
      </el-row>
      <el-row>
        <h1 class="title">asc加密(使用CryptoJS插件)</h1>
        <span>{{ encrypt(form.password) }}</span>
      </el-row>
      <el-row>
        <h1 class="title">asc解密(使用CryptoJS插件)</h1>
        <span>{{ decrypt(encrypt(form.password)) }}</span>
      </el-row>
      <el-row>
        <span class="detail">
          CryptoJS 是一个 JavaScript
          的加解密的工具包。它支持多种算法:MD5、SHA1、SHA2、SHA3、RIPEMD-160
          的哈希散列,以及进行 AES、DES、Rabbit、RC4、Triple DES 加解密。</span
        >
      </el-row>
      <el-row>
        <h1 class="title">对称(RSA)加密:jsencrypt</h1>
        <span>{{ RSAEncode(form.password) }}</span>
      </el-row>
      <el-row>
        <el-col :span="14">
          <span class="detail">
            关于该加密模块,出现在自己做的一个后台管理系统项目中,前端是vue,后端是Java。应用的场景是需要前端通过公钥对需要加密的密文进行加密,后端通过私钥对前端加密的密文进行解密。这样能比之前三个能极大的提高密文安全性。相关的使用方式可以参照下面
            关于前端的其他加密解密好文中的第二个。
            这里把关于前端方面简化后的代码贴在下方,可供参考,后端方面的参考下方链接的第二个博文
          </span>
        </el-col>
      </el-row>
      <div></div>
    </el-form>
  </div>
</template>
<script>
  import md5 from 'js-md5' //引入md5加密插件
  import { Base64 } from 'js-base64' //base64加密插件
  import CryptoJS from 'crypto-js' //引入CryptoJS加密插件
  import JSEncrypt from 'jsencrypt' //引入JSEncrypt加密插件
  export default {
    data() {
      return {
        form: {
          password: '123', //密码
        },
        rules: {}, //校验
      }
    },
    methods: {
      passwordChange() {},
      // md5加密(默认32位)
      md5Encode(str) {
        return md5(str)
      },
      // 使用 MD5 加密算法进行16位加密
      md5Encode2(str) {
        return md5(str).substring(8, 24) // 从第8个字符开始截取16位
      },

      // base64加密(方法1--window.btoa)
      base64Encode1(str) {
        return window.btoa(str)
      },
      // base64加密(方法2-- Base64.encode) 使用插件
      base64Encode2(str) {
        return Base64.encode(str)
      },
      // base64加密(方法3--window.btoa)
      /**
       * BASE64加密
       * @param str
       * @returns {string}
       */
      base64Encode3(str) {
        return btoa(unescape(encodeURIComponent(str)))
      },

      /**
       * BASE64解密
       * @param str
       * @returns {string}
       */
      base64Decode(str) {
        return decodeURIComponent(escape(atob(str)))
      },
      // asc加密
      /**
       * 加密方法
       * @param {*} word
       * @param {*} keyStr
       * @param {*} ivStr
       */
      encrypt(word, keyStr, ivStr) {
        // 设置秘钥和偏移量需要和后端一致
        // 十六位十六进制数作为密钥
        const KEY = CryptoJS.enc.Utf8.parse('123456jmff654321')
        // 十六位十六进制数作为密钥偏移量
        const IV = CryptoJS.enc.Utf8.parse('654321jmff123456')
        let key = KEY
        let iv = IV
        if (keyStr) {
          key = CryptoJS.enc.Utf8.parse(keyStr)
          iv = CryptoJS.enc.Utf8.parse(ivStr)
        }
        let srcs = CryptoJS.enc.Utf8.parse(word)
        var encrypted = CryptoJS.AES.encrypt(srcs, key, {
          iv: iv,
          mode: CryptoJS.mode.CBC,
          padding: CryptoJS.pad.ZeroPadding,
        })
        return CryptoJS.enc.Base64.stringify(encrypted.ciphertext)
      },
      //  asc解密
      /**
       * 解密方法
       * @param {*} word
       * @param {*} keyStr
       * @param {*} ivStr
       */
      decrypt(word, keyStr, ivStr) {
        // 设置秘钥和偏移量需要和后端一致
        // 十六位十六进制数作为密钥
        const KEY = CryptoJS.enc.Utf8.parse('123456jmff654321')
        // 十六位十六进制数作为密钥偏移量
        const IV = CryptoJS.enc.Utf8.parse('654321jmff123456')
        let key = KEY
        let iv = IV

        if (keyStr) {
          key = CryptoJS.enc.Utf8.parse(keyStr)
          iv = CryptoJS.enc.Utf8.parse(ivStr)
        }

        let base64 = CryptoJS.enc.Base64.parse(word)
        let src = CryptoJS.enc.Base64.stringify(base64)

        let decrypt = CryptoJS.AES.decrypt(src, key, {
          iv: iv,
          mode: CryptoJS.mode.CBC,
          padding: CryptoJS.pad.ZeroPadding,
        })

        let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8)
        return decryptedStr.toString()
      },
      // 非对称加密密钥生成网站:http://web.chacuo.net/netrsakeypair
      // RSA非对称加密是一种广泛使用的加密算法,它使用两个密钥:一个公钥用于加密数据,一个私钥用于解密数据。在JavaScript中,可以使用CryptoJS库来实现RSA非对称加密。
      // 非对称(RSA)加密:jsencrypt
      RSAEncode(str) {
        let encryptor = new JSEncrypt() // 新建JSEncrypt对象
        let publicKey = `MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuY3BqJVVeLwYF/qk6VeM
ZNKruSQUfAsrz3Hv0ExmK7FdlsgtEBRMpFNylCFw2pbhdFtC0iedr5+DDKqqasUh
boXMRR5KV27Zan96RbyQaqT9oXP6n9d6JBPNxuTglLtnK+FielB8oXmlz8YmOvs6
mH2n6GNoYAFwaNMXPAtiNFk+BbyTeN7t6aejQiidqq8OW87c/B6KD1ffbQBC56u2
CGYHPHjvL4G7QtR3vheXFNXjz2e0iVvHZ5hv/rBXRk9XNnV0eID3/TXlGiCFcyqd
wm6tMV54H9tv9XX00NqhBnKtPIxLTCe5Ys/83K+KuniOYYtLQmy5NLgNaNTm6hCD
ZwIDAQAB` //设置公钥,可以从上面的非对称加密密钥生成网站中得到
        encryptor.setPublicKey(publicKey) // 将得到的公钥通过setPbulicKey方法设置到JSEncrypt对象中
        return encryptor.encrypt(str) // 对需要加密的数据进行加密,rspPassWord就是加密密文
      },
    },
  }
</script>
<style lang="scss" scoped>
  .main {
    width: 100%;
    height: 100%;
    padding: 10px;
    .banner {
      width: 800px;
      height: 600px;
      margin: 0 auto;
      box-sizing: border-box;
      border: 1px solid #ccc;
    }
    .title {
      font-size: 16px;
      // color: rgb(150, 15, 212);
      display: inline-block;
    }
    .detail {
      color: darkgray;
    }
  }
</style>

请添加图片描述

需要注意的是,前端加密并不能保证绝对的安全性,应该结合其他安全措施来提高系统的安全性。同时,在选择加密算法时应该根据具体的需求和场景进行选择,综合考虑安全性和性能等因素。

✒️总结

如果这篇【文章】有帮助到你💖,希望可以给我点个赞👍,创作不易,如果有对前端端或者对python感兴趣的朋友,请多多关注💖💖💖,咱们一起探讨和努力!!!
👨‍🔧 个人主页 : 前端初见

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

无需API实现MySQL与巨量引擎的对接

通过数环通&#xff0c;您可以使用不到几分钟的时间即可实现MySQL与巨量引擎的对接与集成&#xff0c;从而高效实现工作流程自动化&#xff0c;降本增效&#xff01; 1.产品介绍 巨量引擎是字节跳动旗下的营销服务品牌&#xff0c;它整合了字节跳动旗下的产品及海量内容&#…

asp.net购物网站源码-系统销售毕业设计

采用典型的三层架构进行开发&#xff0c;包含购物车、登陆注册、个人中心、留言板、新闻系统&#xff0c;前台页面、后台管理等主要技术&#xff1a;基于asp.net架构和sql server数据库 功能模块&#xff1a; 本源码是一个三层购物网站源码&#xff0c;功能齐全&#xff0c;界面…

【PyQt小知识 - 4】:QGroupBox分组框控件 - 边框和标题设置

QGroupBox QGroupBox 是 PyQt 中的一个小部件&#xff0c;用于创建一个带有标题的组框。 可以使用 QGroupBox 将相关控件分组并添加一个标题。 以下是一个使用 QGroupBox 的示例代码&#xff08;示例一&#xff09;&#xff1a; from PyQt5.QtWidgets import * import sysa…

Linux_虚拟机常用目录汇总

根目录&#xff08;cd /&#xff09;&#xff1a;/ 表示根目录&#xff0c;cd和 / 之间有个空格&#xff01; 用户目录&#xff08;cd ~&#xff09;&#xff1a;~ 表示用户目录&#xff0c;也称为家目录。cd 和 ~ 之间有个空格&#xff01; 当前路径&#xff1a;执行 pwd 指令…

linux运行java程序

这个帖子实现的是linux上运行java代码 文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 事情发生的原因是博洋需要知道海外城市的数量&#xff0c;我一开始准备将全量数据拉取到本地&#xff0c;用代码遍历一遍。但是打包好全量数据&…

SystemVerilog学习 (9)——随机化

目录 一、概述 二、随机化 2.1、如何简单地产生一个随机数 2.1.1 利用系统函数产生随机数 2.1.2 urandom() 2.2、什么需要随机化 2.3、随机约束 2.3.1 rand 和 randc 2.3.2 随机约束的使用 2.3.3 约束块 三、总结 一、概述 随着设计变得越来越大,要产生一个完整的激…

vivado产生报告阅读分析6-时序报告2

1、复查时序路径详情 单击“ OK ”运行报告命令后 &#xff0c; 将打开一个新窗口。这样您即可复查其中内容。在其中可查看执行选定的每种类型 (min/max/min_max ) 的分析之后所报告的 N 条最差路径。 下图显示的“Report Timing ” &#xff08; 时序报告 &#xff09; 窗口…

知识梳理到了领域榜一,意外,开心。

我的护城河 就是掌握的不断更新的技术。 一直被认可的能力。 完美的项目交付。 写的文章得到了读者们的认可。 希望我做的努力被更多的人看到。 分享的代码片可以解决他人的问题。 很惊喜&#xff0c;今早我的文章被数据结构和算法领域内容榜排到了第一名。 被认可的感觉很棒。…

基于IGT-DSER实现工业触摸屏与PLC设备之间WIFI无线通讯

本文是基于IGT-DSER系列智能网关设备实现工业触摸屏与PLC设备之间WIFI无线通讯的案例。PLC之间无线通讯的案例 网络结构如下图&#xff0c;触摸屏通过网线连接IGT-DSERWIFI智能网关&#xff0c;实现WIFI的AP功能&#xff1b;一台串口型PLC和一台网口型PLC分别通过IGT-WSER智能网…

接口自动化测试面试题

前言 前面总结了一篇关于接口测试的常规面试题&#xff0c;现在接口自动化测试用的比较多&#xff0c;也是被很多公司看好。那么想做接口自动化测试需要具备哪些能力呢&#xff1f; 也就是面试的过程中&#xff0c;面试官会考哪些问题&#xff0c;知道你是不是真的做过接口自动…

【第2章 Node.js基础】2.7 Node.js 的流(一)可写流

&#x1f308;可写流 &#x1f680;什么是可写流 可写流是对数据被写入的目的地的一种抽象。 所有可写流都实现了 stream.Writable类定义的接口。 可写流的例子包括&#xff0c;也都是实现了可写流接口的双工流 客户端的 HTTP 请求、服务器的HTTP 响应、fs 的写入流、zlib…

JUNIT使用和注意、以及断言的介绍使用、SpringBoot Test测试类的使用、maven配置使用junit详细介绍

参考文章&#xff1a; https://www.cnblogs.com/zhukaile/p/14514238.html&#xff0c;https://blog.csdn.net/qq_36448800/article/details/126438339 一、什么是单元测试 在平时的开发当中&#xff0c;一个项目往往包含了大量的方法&#xff0c;可能有成千上万个。如何去保…

最小生成树

目录 带权图 带权图java代码实现 最小生成树 Kruskal算法 ​切分定理 Kruskal算法的java代码实现 Prim算法 Prim算法的java代码实现 总结 带权图 边上的权是附加的额外信息&#xff0c;可以代表不同公路的收费等你需要的信息。 带权图java代码实现 port java.io.File…

mysql---squid代理服务器

squid代理服务器 nginx也可以代理&#xff1a;反向代理--------负载均衡 squid:正向代理服务器。例&#xff1a;vpn squid &#xff1a;正向代理&#xff0c;缓存加速&#xff0c;acl过滤控制 代理的工作机制 1、代替客户端向网站请求数据&#xff0c;不需要访问代理的IP地址…

AI时代,如何防范诈骗的建议

以下是一些防范AI诈骗的方法&#xff1a; 认知教育&#xff1a;了解AI技术的应用和局限性&#xff0c;学习如何识别虚假信息和诈骗手段。保护个人信息&#xff1a;不要轻易泄露个人信息&#xff0c;尤其是身份证号码、银行卡号等敏感信息。谨慎对待陌生人的联系和信息&#xf…

前后端分离项目在Linux的部署方法、一台Nginx如何部署多个Web应用

需求场景:目前有三个前后端分离项目(vue+springboot),Linux服务器一台,nginx一个,比如服务器地址为www.xxxxxxx.com 我想通过80端口访问服务①(即访问www.xxxxxxx.com);通过81端口访问服务②(即www.xxxxxxx.com:81);通过82端口访问服务③(即www.xxxxxxx.com:82) ①部…

Java抽象类和接口

抽象类 看看这个代码 class Shape{public void draw(){System.out.println("画图形");} } class Cycle extends Shape{Overridepublic void draw() {System.out.println("⚪");} } class Rect extends Shape{Overridepublic void draw() {System.out.pri…

一个集成了AI和BI报表功能的新一代数据库管理系统神器--Chat2DB

世人皆知Navicate&#xff0c;无人识我Chat2DB &#x1f4d6; 简介 Chat2DB 是一款开源免费的多数据库客户端工具&#xff0c;支持多平台和主流数据库。 集成了AI的能力&#xff0c;能进行自然语言转SQL、SQL解释、SQL优化、SQL转换 ✨ 好处 1、AIGC和数据库客户端的联动&am…

[Vue 代码模板] Vue3 中使用 Tailwind CSS + NutUI 实现侧边工具栏切换主题

文章归档&#xff1a;https://www.yuque.com/u27599042/coding_star/vzkgy6gvcnpl3u2y 效果示例 配置 src 目录别名 https://www.yuque.com/u27599042/coding_star/ogu2bhefy1fvahfv 配置 Tailwind CSS https://www.yuque.com/u27599042/coding_star/yqzi9olphko9ity1 配置…

各地区农村及城镇恩格尔系数数据集(1978-2022年)

恩格尔系数是以德国统计学家恩格尔&#xff08;Ernst Engel&#xff09;的名字命名的一个经济指标&#xff0c;用来衡量食品支出占家庭总支出的比例。一般来说&#xff0c;恩格尔系数越低&#xff0c;表明家庭在食品上的支出占比越小&#xff0c;相对而言家庭的生活水平和经济条…