首页
统计
Search
1
TypeScript学习笔记
5 阅读
2
《被讨厌的勇气》读后感
5 阅读
3
从零开始的Vue学习
3 阅读
4
摘抄
3 阅读
5
【极客时间】玩转Git三剑客笔记
3 阅读
年度总结
学习笔记
读后感
动漫汇总
日常记录
登录
Search
标签搜索
大数据
git
加密
Vue
CTF
TypeScript
React
Augenstern
累计撰写
10
篇文章
累计收到
0
条评论
首页
栏目
年度总结
学习笔记
读后感
动漫汇总
日常记录
页面
统计
搜索到
8
篇与
学习笔记
的结果
2025-12-03
React Hook学习
参考链接: React 内置 HookHook简单介绍 定义: 以use开头的函数 作用: Hook有助于在组件中使用不同的React功能 使用: Hook比普通函数更为严格,只能在的组件(或其他 Hook)的 顶层 调用Hook 分类:State HookContext HookRef HookEffect Hook性能 Hook其他 Hook自定义 HookState Hook状态帮助组件,用于“记住”用户的输入信息useState :声明可以直接更新的状态变量示例:function MyButton(){ const [count,setCount] = useState(0); function handleClick(){ setCount(count+1); } return( <button onClick={handleClick}> Clicked {count} times </button> ) }useReducer:在reducer函数中声明带有更新逻辑的state变量reducer函数 :将组件的所有状态更新逻辑整合到一个外部函数中,这个函数叫做reduceruseReducer钩子接受参数:一个reducer函数一个初始的state返回内容:一个有状态的值一个dispatch函数(派发用户操作给reducer)示例: {tabs}{tabs-pane label="App.js"}import { useReducer } from 'react'; import AddTask from './AddTask.js'; import TaskList from './TaskList.js'; import tasksReducer from './tasksReducer.js'; export default funtion TaskApp(){ const [tasks, dispatch] = useReducer(tasksReducer, initialTasks); function handleAddTask(text){ dispatch({ type:'added', id:nextId++, text:text, }); } function handleChangeTask(task){ dispatch({ type:'changed', task:task }); } function handleDeleteTask(taskId){ dispatch({ type:'deleted', id:taskId, }); } return ( <> <h1>布拉格的行程安排</h1> <AddTask onAddTask={handleAddTask} /> <TaskList tasks={tasks} onChangeTask={handleChangeTask} onDeleteTask={handleDeleteTask} /> </> ); }{/tabs-pane}{tabs-pane label="tasksReducer.js"}export default function tasksReducer(tasks, action) { switch (action.type) { case 'added': { return [ ...tasks, { id: action.id, text: action.text, done: false, }, ]; } case 'changed': { return tasks.map((t) => { if (t.id === action.task.id) { return action.task; } else { return t; } }); } case 'deleted': { return tasks.filter((t) => t.id !== action.id); } default: { throw Error('未知 action:' + action.type); } } } {/tabs-pane}{/tabs}Context Hook上下文帮助组件 从祖先组件接收信息,而无需将其作为 props 传递useContext 读取订阅上下文示例:import { createContext, useContext } from 'react'; const ThemeContext = createContext(null); export default function MyApp(){ return ( <ThemeContext.Provider value="dark"> <Form/> <ThemeContext.Provider> ); } function Form(){ return ( <Panel title="Welcome"> <Button>Sign up </Button> <Button>Log in </Button> </Panel> ); } function Panel({title,children}){ const theme = useContext(ThemeContext); const className = 'panel-' + theme; return( <section className = {className}}> <h1>{title}</h1> {children} </section> ); } funciton Button({children}){ const theme = useContext(ThemeContext); const className = 'button-' + theme; return( <button className={className}> {children} </button> ); }注意:通常情况下,useContext()只会调用上层provider,当然通过合并的方式可以实现嵌套调用Ref Hookref 允许组件 保存一些不用于渲染的信息,比如 DOM 节点或 timeout ID。与状态不同,更新 ref 不会重新渲染组件。useRef 声明ref,可以保存任何值,但常用于保存DOM节点示例:import { useRef } from 'react'; export default function Counter() { let ref = useRef(0); function handleClick() { ref.current = ref.current + 1; alert('You clicked ' + ref.current + ' times!'); } return ( <button onClick={handleClick}> 点击!{ref.current} </button> ); } 与useState不同的是,ref不会触发重新渲染,所以JSX中显示{ref.current}不会变化useImperativeHandle 自定义从组件中暴露ref,不常用Effect HookEffect 允许组件 连接到外部系统并与之同步。这包括处理网络、浏览器、DOM、动画、使用不同 UI 库编写的小部件以及其他非 React 代码useEffect 将组件连接到外部系统外部系统 :有些组件需要与网络、某些浏览器 API 或第三方库保持连接,当它们显示在页面上时。这些系统不受 React 控制,所以称为外部系统示例:import {useState,useEffect} from 'react'; import {createConnection} from './chat.js'; function ChatRoom({roomId}){ const [serverUrl,setServerUrl] = useState('https://localhost:1234'); useEffect(()=>{ const connection = createConnection(serverUrl,roomId); connection.connect(); return ()=>{ connection.disconnection(); }; },[serverUrl,roomId]); // ... }需要向 useEffect 传递两个参数:一个 setup 函数 ,其 setup 代码 用来连接到该系统。它应该返回一个 清理函数(cleanup),其 cleanup 代码 用来与该系统断开连接。一个 依赖项列表,包括这些函数使用的每个组件内的值性能 Hook使用性能hook可以跳过计算和不必要的重新渲染来优化性能useMemo 缓存计算代价昂贵的计算结果useMemo(calculateValue, dependencies) calculateValue:要缓存计算值的函数 dependencies:所有在 calculateValue 函数中使用的响应式变量组成的数组示例: {tabs}{tabs-pane label="App.js"}import { useState } from 'react'; import { createTodos } from './utils.js'; import TodoList from './TodoList.js'; const todos = createTodos(); export default funtion App(){ const [tab,setTab] = useState('all'); const [isDark,setIsDark] = useState(false); return( <> <button onClick={()=>setTab('all')}>All</button> <button onClick={()=>setTab('active')}>Active</button> <button onClick={()=>setTab('completed')}>Completed</button> <br/> <label> <input type="checkbox" checked={isDark} onChange={e=>setIsDark(e.target.checked)}> Dark mode </input> </label> <hr/> <TodoList todos={todos} tab={tab} theme={isDark?'dark':'light'}/> </> ); } {/tabs-pane}{tabs-pane label="TodoList.js"}import { useMemo } from 'react'; import { filterTodos } from './utils.js' export default function TodoList({ todos, theme, tab }) { const visibleTodos = useMemo( () => filterTodos(todos, tab), [todos, tab] ); return ( <div className={theme}> <p><b>Note: <code>filterTodos</code> is artificially slowed down!</b></p> <ul> {visibleTodos.map(todo => ( <li key={todo.id}> {todo.completed ? <s>{todo.text}</s> : todo.text } </li> ))} </ul> </div> ); } {/tabs-pane}{tabs-pane label="utils.js"}export function createTodos() { const todos = []; for (let i = 0; i < 50; i++) { todos.push({ id: i, text: "Todo " + (i + 1), completed: Math.random() > 0.5 }); } return todos; } export function filterTodos(todos, tab) { console.log('[ARTIFICIALLY SLOW] Filtering ' + todos.length + ' todos for "' + tab + '" tab.'); let startTime = performance.now(); while (performance.now() - startTime < 500) { // 在 500 毫秒内不执行任何操作以模拟极慢的代码 } return todos.filter(todo => { if (tab === 'all') { return true; } else if (tab === 'active') { return !todo.completed; } else if (tab === 'completed') { return todo.completed; } }); } {/tabs-pane}{/tabs}useCallback 将函数传递给优化组件之前缓存函数定义const cachedFn = useCallback(fn, dependencies) fn:想要缓存的函数 dependencies:有关是否更新 fn 的所有响应式值的一个列表示例:function ProductPage({ productId, referrer, theme }) { // 在多次渲染中缓存函数 const handleSubmit = useCallback((orderDetails) => { post('/product/' + productId + '/buy', { referrer, orderDetails, }); }, [productId, referrer]); // 只要这些依赖没有改变 return ( <div className={theme}> {/* ShippingForm 就会收到同样的 props 并且跳过重新渲染 */} <ShippingForm onSubmit={handleSubmit} /> </div> ); }useMemo与useCallback联系useMemo 经常与 useCallback 一同出现,区别在于useMemo 缓存函数调用的结果 useCallback 缓存函数本身// 在 React 内部的简化实现 function useCallback(fn, dependencies) { return useMemo(() => fn, dependencies); }示例:import { useMemo, useCallback } from 'react'; function ProductPage({ productId, referrer }) { const product = useData('/product/' + productId); const requirements = useMemo(() => { //调用函数并缓存结果 return computeRequirements(product); }, [product]); const handleSubmit = useCallback((orderDetails) => { // 缓存函数本身 post('/product/' + productId + '/buy', { referrer, orderDetails, }); }, [productId, referrer]); return ( <div className={theme}> <ShippingForm requirements={requirements} onSubmit={handleSubmit} /> </div> ); }其他 Hook使用 useDebugValue 自定义 React 开发者工具为自定义 Hook 添加的标签。使用 useId 将唯一的 ID 与组件相关联,其通常与可访问性 API 一起使用。使用 useSyncExternalStore 订阅外部 store。使用 useActionState 允许你管理动作的状态.自定义Hook自定义hook
2025年12月03日
1 阅读
0 评论
0 点赞
2025-10-24
摘抄
{card-default label="刘震云" width=""}这个世界我们只来一次,百年之后,没你也没我 我们拼搏一生,带不走一砖一瓦 我们执着一生,带不走一丝爱恨情仇,人生苦短 所以吃你想吃的饭,见你想见的人,看你喜欢的风景,做你喜欢的事 人生本来就是一次减法,来日并不方长 有钱把日子过好,没钱把心情过好,时间扑面而来 我们终将释怀 平静的过,健康的活着 开心地笑,适当地忙碌 就很好 不要去责怪你生命中的任何人,合得来就好好相处,多多关怀,合不来就保持距离,装装糊涂 人在世上总会遇见形形色色的人,好的人给了你快乐 坏的人给了你经历,最差的人给了你教训,最好的人给了你成长 所有的相遇绝非偶然 来者要惜,去者要放 {/card-default}{card-default label="白日梦想家" width=""}认识世界,克服困难。洞悉所有,贴近生活。寻找真爱,感受彼此。这就是生活的意义。{/card-default}
2025年10月24日
3 阅读
0 评论
0 点赞
2025-10-17
TypeScript学习笔记
TypeScript入门笔记教程地址:官方文档:TypeScript 菜鸟教程:TypeScript入门教程简单介绍1、TypeScript由微软公司开发,是一种开源的编程语言2、TypeScript是JavaScript的超集,拓展了JavaScript的语法,因此,TS也是兼容JS代码的,只会对TS代码进行编译安装有两种主要的方式来获取TypeScript工具:通过npm(Node.js包管理器)安装Visual Studio的TypeScript插件这里采用npm的方式进行安装npm install -g typescript查看版本tsc -V 初始化一个项目tsc --init 基础语法数据类型布尔值let isDone: boolean = false;数字let decLiteral: number = 6; //十进制 let hexLiteral: number = 0xf00d; //十六进制 let binaryLiteral: number = 0b1010; //二进制 let octalLiteral: number = 0o744; //八进制字符串let name: string = "bob"; name = "smith";字符串除用"或'表示外,还可以使用模板字符串,可以定义多行文本和内嵌表达式,字符串由反引 号`包围,并且以${ expr }这种形式嵌入表达式let name: string = `Xiaohu`; let age: number = 37; let sentence: string = `Hello, my name is ${name}. I'll be ${age+1} years old next month;` console.log(sentence); //显示结果 Hello, my name is Xiaohu. I'll be 38 years old next month;SymbolSymbol 是 唯一且不可变 的数据类型,通常用作对象属性的键// Symbol 类型注解 const sym1: symbol = Symbol(); const sym2: unique symbol = Symbol("key"); // unique symbol 类型 // 作为对象属性 const obj = { [sym2]: "123" // 使用 unique symbol }; console.log(obj[sym2]); // "123"数组两种定义方式第一种在元素类型后面添加[]let list: number[] = [1, 2, 3];第二种使用数组放心,Array<元素类型>let list: Array<number>元组元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同let x: [string, number]; x = ['hello', 10]; // 正确 x = [10, 'hello']; // 错误当访问一个越界的元素,会使用 联合类型 替代x[3] = 'world'; x[4] = 100; console.log(x[5].toString()); //以上都是可以的, 字符串和数字都属于(string | number)类型,'string' 和 'number' 都有 toString x[6] = true; // Error, 布尔不是(string | number)类型联合类型一个变量是多个数据类型中的某一个,可以使用联合类型, 或 的关系function getArg(param: string | number) { return param.length }交叉类型一个变量是多个数据类型的总和,可以使用交叉类型, 与 的关系interface Person { name: string; age: number; } interface Employee { company: string; employeeId: number; } // BusinessPerson 必须同时拥有 Person 和 Employee 的所有属性 type BusinessPerson = Person & Employee;枚举enum类型是对JavaScript标准数据类型的一个补充,使用枚举类型可以为一组数值赋予友好的名字enum Color {Red,Green,Blue} let c:Color = Color.Green; console.log(c); //显示1默认情况下,从0开始为元素编号,也可以手动的指定成员的数值;枚举类型也可以通过值找到对应名字enum Color {Red=1,Green=2,Blue=4} //Green和Blue 不赋值,则默认从2开始 let colorName:string = Color[4]; console.log(colorName); // 显示BlueAnyAny表示任意类型,但不同在于Object只允许赋值,而不能调用其中的方法,即使对象内部真的有对应的方法let notSure: any = 4; notSure.ifItExists(); // 正常 notSure.toFixed(); // 正常 let prettySure: Object = 4; prettySure.toFixed(); // 报错,提示Object没有对应方法Void表示没有任何类型,比如在函数没有返回值时,返回voidfunction warnUser(): void { console.log("This is my warning message"); }void 只能赋undefined和nulllet unusable: void = undefined;Null 和 UndefinedTypeScript里,undefined和null两者各自有自己的类型分别叫做undefined和null,是所有类型的子类型(默认情况);--strictNullChecks标记,null和undefined只能赋值给void和它们各自Nevernever类型表示的是那些永不存在的值的类型,never类型是任何类型的子类型,也可以赋值给任何类型;然而,没有类型是never的子类型或可以赋值给never类型(除了never本身之外), 即使 any也不可以赋值给never。// 返回never的函数必须存在无法达到的终点 function error(message: string): never { throw new Error(message); } // 推断的返回值类型为never function fail() { return error("Something failed"); } // 返回never的函数必须存在无法达到的终点 function infiniteLoop(): never { while (true) { } }Objectobject表示非原始类型,也就是除number,string,boolean,symbol,null或undefined之外的类型接口TypeScript的核心原则之一是对值所具有的shape进行类型检查。 它有时被称做“鸭式辨型法”或“结构性子类型化”。 在TypeScript里,接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约普通接口interface LabelledValue{ label:string; } function printLabel(labelledObj:LabelledValue){ console.log(labelledObj.label); } let myObj = {size:10,label:"Size 10 Object"}; printLabel(myObj);LabelledValue接口就好比一个名字,用来描述上面例子里的要求。它代表了有一个label属性且类型为string的对象。需要注意的是,我们在这里并不能像在其它语言里一样,说传给printLabel的对象实现了这个接口。我们只会去关注值的外形。 只要传入的对象满足上面提到的必要条件,那么它就是被允许的。还有一点值得提的是,类型检查器不会去检查属性的顺序,只要相应的属性存在并且类型也是对的就可以。可选属性带有可选属性的接口与普通的接口定义差不多,只是在可选属性名字定义的后面加一个?符号,可选属性的好处之一是 可以对可能存在的属性进行预定义 ,好处之二是 可以捕获引用了不存在的属性时的错误interface SquareConfig { color?: string; width?: number; }只读属性一些对象属性只能在对象刚刚创建的时候修改其值,可以在属性名前用readonly来指定只读属性属性用readonly,变量用constinterface Point { readonly x: number; readonly y: number; } }函数类型接口也可以描述函数类型interface SearchFunc{ (source:string,subString:string):boolean; } let mySearch: SearchFunc; mySearch = function(source: string, subString: string) { let result = source.search(subString); if (result == -1) { return false; } else { return true; } } //对于函数类型的类型检查来说,函数的参数名不需要与接口里定义的名字相匹配 mySearch = function(src: string, sub: string): boolean { let result = src.search(sub); if (result == -1) { return false; } else { return true; } }数组类型数组类型具有一个index类型表示索引的类型,还有一个相应的返回值类型表示通过索引得到的元素的类型interface StringArray { [index: number]: string; } let myArray: StringArray; myArray = ["Bob", "Fred"];interface NumberDictionary { [index: string]: number; length: number; // 可以,length是number类型 name: string // 错误,`name`的类型不是索引类型的子类型 }实现接口与Java中的接口一致,TypeScript也能够用它来明确的强制一个类去符合某种契约interface ClockInterface { currentTime: Date; setTime(d: Date); } class Clock implements ClockInterface { currentTime: Date; setTime(d: Date) { this.currentTime = d; } constructor(h: number, m: number) { } }类静态部分与实例部分实例部分 :当你使用 new 创建一个类的实例时,实例上拥有的属性和方法。静态部分 :类本身(构造函数)上拥有的属性和方法。当你用一个接口去约束一个类时(使用 implements 关键字),这个接口 只会检查类的实例部分,而不会检查静态部分 。当你用 构造器签名 (用来描述构造函数类型的一种特殊语法)去定义一个接口并试图定义一个类去实现这个接口时会得到一个错误,因为当一个类实现了一个接口时,只对其实例部分进行类型检查。 constructor存在于类的静态部分,所以不在检查的范围内。interface ClockConstructor { new (hour: number, minute: number); } class Clock implements ClockConstructor { currentTime: Date; constructor(h: number, m: number) { } }因此,我们应该直接操作类的静态部分。 看下面的例子,我们定义了两个接口, ClockConstructor为构造函数所用和ClockInterface为实例方法所用。 为了方便我们定义一个构造函数 createClock,它用传入的类型创建实例。interface ClockConstructor { new (hour: number, minute: number): ClockInterface; } interface ClockInterface { tick(); } function createClock(ctor: ClockConstructor, hour: number, minute: number): ClockInterface { return new ctor(hour, minute); } class DigitalClock implements ClockInterface { constructor(h: number, m: number) { } tick() { console.log("beep beep"); } } class AnalogClock implements ClockInterface { constructor(h: number, m: number) { } tick() { console.log("tick tock"); } } let digital = createClock(DigitalClock, 12, 17); let analog = createClock(AnalogClock, 7, 32);因为createClock的第一个参数是ClockConstructor类型,在createClock(AnalogClock, 7, 32)里,会检查AnalogClock是否符合构造函数签名继承接口接口可以相互继承,也可以继承多个接口,创建出多个接口的合成接口interface Shape { color: string; } interface PenStroke { penWidth: number; } interface Square extends Shape, PenStroke { sideLength: number; } let square = <Square>{}; square.color = "blue"; square.sideLength = 10; square.penWidth = 5.0;接口继承类当接口继承了一个类类型时,它会继承类的成员但不包括其实现。当创建了一个接口继承了一个拥有私有或受保护的成员的类时,这个接口类型只能被这个类或其子类所实现(implement)class Control { private state: any; } interface SelectableControl extends Control { select(): void; } class Button extends Control implements SelectableControl { select() { } } class TextBox extends Control { select() { } } // 错误:“Image”类型缺少“state”属性。 class Image implements SelectableControl { select() { } } class Location { }类与Java中的类很类似,成员有属性、构造方法、方法class Greeter { greeting: string; constructor(message: string) { this.greeting = message; } greet() { return "Hello, " + this.greeting; } } let greeter = new Greeter("world");继承派生类通常被称作子类 ,基类通常被称作 超类class Animal { move(distanceInMeters: number = 0) { console.log(`Animal moved ${distanceInMeters}m.`); } } class Dog extends Animal { bark() { console.log('Woof! Woof!'); } } const dog = new Dog(); dog.bark(); dog.move(10); dog.bark();公共,私有与受保护的修饰符public:默认值,可以自由的访问类中定义的成员private:不能在声明它的类的外部访问;只用两个类中都有相同private成员,且来自同一处声明时,这两个类型才是兼容的,protected成员也一样protected:protected成员在派生类中仍然可以访问其他知识点1、readonly修饰符可以使用readonly关键字将属性设置为只读的。只读属性必须在声明时或构造函数里被初始化2、存取器TypeScript支持通过getters/setters来截取对对象成员的访问3、静态属性创建类的静态成员,这些属性存在于类本身上面而不是类的实例上4、抽象类abstract,抽象类做为其它派生类的基类使用函数普通函数和匿名函数// Named function function add(x, y) { return x + y; } // Anonymous function let myAdd = function(x, y) { return x + y; };this和箭头函数箭头函数能保存函数创建时的 this值,而不是调用时的值let deck = { suits: ["hearts", "spades", "clubs", "diamonds"], cards: Array(52), createCardPicker: function() { // NOTE: the line below is now an arrow function, allowing us to capture 'this' right here return () => { let pickedCard = Math.floor(Math.random() * 52); let pickedSuit = Math.floor(pickedCard / 13); return {suit: this.suits[pickedSuit], card: pickedCard % 13}; } } } let cardPicker = deck.createCardPicker(); let pickedCard = cardPicker(); alert("card: " + pickedCard.card + " of " + pickedCard.suit);泛型使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据Hello World不使用any类型是因为any会导致这个函数可以接收任何类型的arg参数,这样就丢失了一些信息:传入的类型与返回的类型应该是相同的function identity<T>(arg: T): T { return arg; }类型推论 :编译器会根据传入的参数自动地帮助我们确定T的类型let output = identity("myString"); 泛型约束<T extends Lengthwise>:这是泛型约束,表示类型 T 必须满足 Lengthwise 接口的要求interface Lengthwise { length: number; } function loggingIdentity<T extends Lengthwise>(arg: T): T { console.log(arg.length); return arg; }
2025年10月17日
5 阅读
0 评论
0 点赞
2025-01-24
【极客时间】玩转Git三剑客笔记
第一章 Git基础1.1 课程综述版本变更管理 VCS的演化目录拷贝--> 集中式VCS(SVN) --> 分布式VCS(Git)Git优点:开源、性能好、存储优、方面备份、易于制定工作流程、支持离线操作1.2 安装Git安装地址:Git官网1.3 使用Git之前需要做的最小配置 最小配置 git config --global user.name 'your_name' git config --global user.email 'your_email@domain.com' config的三个作用域 git config --local 针对某个仓库(可缺省) git config --global 当前所有用的仓库 git config --system 系统所有登录用户 显示config的配置 git config --list --local 1.4 创建第一个仓库并配置local用户信息两种方式1、把已有的项目代码纳入Git管理 cd 项目代码所在的文件夹 git init 2、新建的项目直接用Git管理 cd 某个文件夹 git init your_project #会在当前路径下创建和项目名称同名的文件夹 cd your_project1.5 通过几次commit来认识工作区和暂存区 工作区 ==> 暂存区 ==> HEAD ==> 远端 add commit push/pull(fetch+merge) git add -u:添加文件的修改,文件的删除(只操作跟踪过的文件) git add . :添加文件的修改,文件的新建 git add -A:添加文件的修改,文件的删除,文件的新建(全部文件) 工作中一般是用到 git add . 或者 git add -A(-all) 1.6 给文件重命名的简便方法 文件重命名: git mv oldName newName 大小写问题: git config core.ignorecase true1.7 通过git log查看版本演变历史ps: 对于git命令参数 如果单字母用-,如果单词使用-- git log --all 查看所有分支的历史 git log --all --graph 查看图形化的 log 地址 git log --oneline 查看单行的简洁历史 git log --oneline -n4 查看最近的四条简洁历史。 git log --oneline --all -n4 --graph 查看所有分支最近 4 条单行的图形化历史。 git help --web log 跳转到git log 的帮助文档网页1.8 gitk:通过图形界面工具来查看版本历史个人日常工作使用souceTree更多1.9 探秘.git目录 .git/ ├── HEAD # 指向当前分支的引用(如 `refs/heads/main`) ├── config # 仓库的本地配置(用户名、远程仓库等) ├── objects/ # 存储所有Git对象(提交、树、文件内容) │ ├── pack/ # 压缩后的对象包(优化存储) │ └── ... # 松散对象(未被压缩的单个对象) ├── refs/ # 存储引用(分支、标签、远程跟踪分支) │ ├── heads/ # 本地分支(如 `main`, `dev`) │ ├── tags/ # 标签(如 `v1.0.0`) │ └── remotes/ # 远程跟踪分支(如 `origin/main`) ├── index # 暂存区(Staging Area)的二进制表示 ├── hooks/ # 客户端/服务端钩子脚本(示例,默认未激活) ├── logs/ # 记录所有分支的提交历史(用于 `git reflog`) └── info/ # 全局排除文件配置(如 `.git/info/exclude`) git cat-file git cat-file -t 查看git 对象的类型 git cat-file -p 查看git 对象的内容 git cat-file -s 查看git 对象的大小1.10 commit、tree和blob三个对象之间的关系blob ==> tree ==> commit 享元模式:一种结构型设计模式,旨在通过共享对象来减少内存使用和提高性能,特别适用于存在大量相似对象的情况。享元模式的核心思想是将对象的内在状态(可共享的部分)与外在状态(不可共享的部分)分离,从而减少对象的数量。 1.11 小练习:数一数tree的个数可以简单的理解为commit是根节点,tree是子节点,blob是叶子节点,其中blob是可以共用的。1.12 分离头指针情况下的注意事项直接git checkout commitId会出现分离头指针的情况,这个时候提交的代码没有与分支关联起来,在切换分支时容易丢失代码(恢复比较麻烦)。应用场景:做测试时,可以用这个方法,不需要则直接丢弃,需要的话则创建新分支 git branch <新分支的名称> commitId1.13 进一步理解HEAD和branchHEAD总结:1、HEAD当和分支挂钩的时候,指向的是该分支的最新提交2、HEAD不和分支挂钩,而是指向某个commit,此时处于分离头指针的状态3、切换分支HEAD的状态:切换分支时,HEAD指向的时branch的最新提交4、HEAD指向branch的时候,指代的是某个具体的commit5、HEAD 代表当前分支最新的提交,HEAD^ 上一个commit,HEAD ^^:上上个commit,HEAD~N:前n个commit第二章 独自使用Git时的场景2.1 怎么删除不需要的分支 git branch -d branch_name 在删除分支前Git会判断在该分支上开发的功能是否被merge的其它分支 git branch -D branch_name2.2 怎么修改最新的commit的message git commit --amend 不只是修改最新commit的message 而是会创建一个将暂存区的内容生成一个commit,再将当前最新的commit替换成新生成的那一个 Linux下 git默认的文本编辑器是nano,很多快捷键不熟悉,执行下面的命令可以将git的文本编辑器改为我们熟悉的vim git config --global core.editor vim2.3 怎么修改老旧commit的message 变基操作 git rebase -i <commit> git rebase -i --root 修改根节点 -r,reword <commit> 使用提交,同时修改提交信息2.4 怎样把连续的多个commit整理成1个 git rebase -i <commit> -s,squash <commit> 使用提交,同时合并到之前的提交中2.5 怎样把间隔的几个commit整理成1个 git rebase -i <commit> -s,squash <commit> 使用提交,其他行加上-s commit id2.6 怎么比较暂存区和HEAD所含文件的差异 git diff --cached2.7 怎么比较工作区和暂存区所含文件的差异 git diff ps: git diff HEAD # 工作区 <===> HEAD git diff # 工作区 <===> 缓存区 git diff --cached # 缓存区 <===> HEAD2.8 如何让暂存区恢复和HEAD的一样 git reset HEAD git reset 有三个参数 --soft 只修改HEAD,暂存区、工作区不变 --hard HEAD、暂存区、工作区均修改 --mixed 默认参数,修改HEAD和暂存区,但工作区保持不变2.9 如何让工作区的文件恢复和暂存区一样 git checkout/git restore -- fileName2.10 怎样取消暂存区部分文件的更改 git reset HEAD -- fileName2.11 消除最近的几次提交 方法一: git rebase -i <commit> 改成 d 方法二: git reset--hard hash值 2.12 看看不同提交的指定文件的差异 git diff commit-id1 commit-id2 path-to-filename2.13 正确删除文件的方法 git rm file name2.14 开发中临时加塞了紧急任务怎么处理 git stash 把当前工作区的内容放入暂存区 git stash pop 把暂存区的内容恢复到工作区,且删除 git stash apply 把暂存区的内容恢复到工作区,且保留2.15 如何指定不需要Git管理的文件 通过.gitignore设置git不用管理文件或文件夹2.16 如何将Git仓库备份到本地 git clone xxx.git第三章 Git与GitHub的简单同步3.1 注册一个GitHub账号已注册 https://github.com/augenstern3263.2 配置公私钥https://github.com/settings/keys3.3 在GitHub上创建个人仓库无3.4 把本地仓库同步到GitHub无第四章 Git与多人单分支集成协作时的常见场景4.1 不同人修改了不同文件如何处理 不受影响,直接提交即可 git add git commit git pull(git fetch+merge) git push4.2 不同人修改了同文件的不同区域如何处理不会产生冲突,但提交前一样git pull拉一下远端代码,保持与远端一致4.3 不同人修改了同文件的同一区域如何处理会产生冲突,手动解决冲突后再进行提交操作4.4 同时变更了文件名和文件内容如何处理当多人修改同一文件的文件名和内容时,Git 会检测到冲突。处理步骤如下:拉取最新代码:先拉取远程仓库的最新代码git pull origin branch-name解决冲突:Git 会提示冲突,手动解决冲突后,将文件添加到暂存区并提交# 解决冲突后 git add <file> git commit -m "Resolved conflict in <file>"推送更改:将解决后的代码推送到远程仓库git push origin branch-name 4.5 把同一文件改成了不同的文件名如何处理拉取最新代码:先拉取远程仓库的最新代码git pull origin branch-name检查文件差异:检查两个文件的内容,决定保留哪个或合并内容。git diff fileA.txt fileB.txt解决冲突:Git 会提示冲突,手动解决冲突后,将文件添加到暂存区并提交假设保留文件A git add fileA.txt git rm fileB.txt推送更改:将解决后的代码推送到远程仓库git push origin branch-name 第五章 Git集成使用禁忌5.1 禁止向集成分支执行push -f操作 git push -f 强制同步远端和本地相同,导致远端修改的内容丢失 可以使用 git reflog 命令查找历史,然后利用 git reset --hard HAED@{n} 的方式恢复。 5.2 禁止向集成分支执行变更历史的操作个人向远端执行变更历史的操作,会导致抹除一些历史提交信息,影响该分支下其他开发者的
2025年01月24日
3 阅读
0 评论
0 点赞
2024-10-17
CTF竞赛学习(入门)
起因本来凑数参加江苏金融监管局的金融业网络安全竞赛,但莫名其妙就进了决赛,可我们三个人纯门外汉,啥也不懂,公司领导为了不让决赛成绩太难看,请到了外面的某安全公司给我们培训CTF,当然一天速成,学到的东西估计也很入门偏概念,这里简单做个记录。CTF竞赛指南CTF简介CTF(Capture The Flag,夺旗赛)是一种流行于网络安全技术人员之间的一种信息安全技术竞赛。其前身是传统黑客之间网络技术比拼的游戏,以代替之前黑客们通过互相发起真实攻击进行技术比拼的方式。起源于1996年第四届DEFCON。现在已成为全球范围网络安全圈流行的竞赛形式。通常CTF分为三种赛制:解题赛(Jeopardy)、攻防赛(Attack-Defence)和混合赛竞赛模式基本分为解题模式、攻防模式和混合模式。大多题目的内容基本包括web安全,密码学、逆向、二进制安全编程类题目等国内外有很多CTF比赛。解题赛是线上赛通常采取的赛制,题目通常分为多个类型,如Web,Forensic(取证),Crypto(密码学),Binary(二进制)等。团队或个人可以通过解题获得一串具有一定格式的字符串,也就是flag。将flag提交到竞赛平台可以获得积分。题目的难度越大,分值就越高。当比赛结束后,得分最高者胜出。攻防赛是另一种有趣的赛制,常见于线下决赛。攻防赛中,每个队伍都会被分配一台主机或虚拟机,称为gamebox,队员可以通过网络连接到gamebox。而所有队伍的gamebox通过内网连接在一起。每个队伍的gamebox上都运行着多个相同的服务。参赛队伍需要挖掘服务的漏洞,然后攻击其他队伍的服务来获取flag,并提交给计分服务器来获取积分。与此同时,参赛队伍还需要修补自身服务中的漏洞来防止丢分。攻防赛不仅考验了参赛选手的技术水平,还考验了参赛者的体力,因为通常参赛者需要连续混合赛可能采取解题赛和攻防赛的混合模式,也可能是其他形式。WebOWASP基于web渗透测试选用到的手段,OWASP(开放式Web应用程序安全项目)所给出的web危险Top10基本上涵盖 了大部分,其中包含注入漏洞、中断身份认证、敏感数据泄露、xxe、中断访问控制、安全配置错误、xss、反 序列化、使用含有已知漏洞的组件、不足的记录和监控漏洞。注入漏洞失效的身份认证敏感数据泄露XXE失效的访问控制安全配置错误XXS不安全的反序列化使用含有已知漏洞的组件不足的日志记录和监控CSRFCSRF(Cross Site Request Forgery) 是指跨站请求伪造,是一种挟制终端用户在当前已登录的Web应用程 序上执行非本意的操作的攻击方法。攻击者只要借助少许的社会工程诡计,例如通过电子邮件或者是聊天软件发送的链接,受害者一旦点击链接,攻击者就能迫使受害者的浏览器在已经登录过的网站上去执行特定操作。CSRF攻击原理用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发 送请求到网站A;用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站 A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请 求,导致来自网站B的恶意代码被执行。SSRFSSRF(Server-Side Request Forgery: 服务器端请求伪造):是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF攻击的目标是外网无法访问的内部系统。正是因为它是由服务端发起的,所以它能够请求与它相连而与外网隔离的内部系统。危险函数:fsockopen()file_get_contents()curl_exec()信息泄露信息泄露漏洞是由于web服务器没有正确处理一些特殊请求或者系统管理员对于应用设置及操作不规范,泄露服务器或者应用的敏感信息,如用户名,密码、源代码、服务器信息、配置信息、物理路径信息利用等。 该类信息的泄露容易造成恶意人员的利用,为达到进一步的攻击系统打下基础。目录遍历目录遍历漏洞是攻击者向web服务器发送请求,通过在url中或者在有特殊意义的目录中附加”../“、或者附 加”../“的一些变形(如“..”或“..//”甚至其编码),或类似的跨父目录字符串,完成目录跳转,读取操 作系统各个目录下的敏感文件。导致攻击者能够访问未授权的目录,以及能够在未授权的web服务器的根目录外执行命令文件上传文件上传漏洞是指网络攻击者上传了一个可执行的文件到服务器并执行。这里上传的文件可以是木马,病毒, 恶意脚本或者WebShell等。这种攻击方式是最为直接和有效的,部分文件上传漏洞的利用技术门槛非常的低,对于攻击者来说很容易实施。任意文件查看与下载一些网站由于业务需求,往往需要提供文件查看或文件下载功能,但若对用户查看或下载的文件不做限制, 则恶意用户就能够查看或下载任意敏感文件,这就是文件查看与下载漏洞。越权访问顾名思义,这类漏洞是指应用在检查授权(Authorization)时存在纰漏,使得攻击者可以利用一些方式绕 过权限检查,访问或者操作到原本无权访问的代码或内容。水平越权:获取水平层级的权限,比如其他用户的权限信息垂直越权:获取垂直层级的权限,比如说普通用户获取admin权限命令执行没有针对代码中可执行的特殊函数入口做过滤,导致客户端可以提交恶意构造语句提交,并交由服务器端执 行。命令注入攻击中WEB服务器没有过滤类似system(),eval(),exec()等函数是该漏洞攻击成功的最主要原因。Crypto之前的密码学笔记CTF-CryptoMisc信息隐写信息隐写技术(隐写术),也称为信息伪装技术,是一门近年来蓬勃发展,已逐渐的在信息安全领域受到关注的学科。它是将某一机密信息秘密隐藏于另一公开的信息(载体)中,然后通过公开信道传输来传递机密信息。第三方难以从公开信息中判断机密信息是否存在,实现隐秘通信或隐蔽标识,保证机密信息的安全与唯一。文件隐写格式类型文件头标识文件尾标识jpeg/jpgFFD8FFD9gif47 49 46 38 39(37) 61 png89 50 4E 47 0D 0A 1A 0A00 00 00 00 49 45 4E 44 AE 42 60 82bmp42 4D(B M) tiff4D 4D 00 2A / 49 49 2A 00 压缩包破解zip/rar爆破Windows下的神器 ARCHPR:暴力枚举,跑字典,明文攻击明文攻击是一种较为高效的攻击手段,大致原理是当你不知道一个zip的密码,但是你有zip中的一个已知文件(文件大小要大于12Byte)或者已经通过其他手段知道zip加密文件中的某些内容时,因为同一个zip压缩包里的所有文件都是使用同一个加密密钥来加密的,所以可以用已知文件来找加密密钥,利用密钥来解锁其他加密文件。CRC32碰撞CRC 本身是「冗余校验码」的意思,CRC32则表示会产生一个32bit(8位十六进制数)的校验值。由于CRC32产生校验值时源数据块的每一个 bit (位)有一位发生了变化,也会得到不同的CRC32值。CRC32校验码出现在很多文件中比如png文件,同样zip中也有CRC32 校验码。值得注意的是zip中的CRC32是未加密文件的校验值。这也就导致了基于CRC32的攻击手法。文件内内容很少(一般比赛中大多为4字节左右)加密的密码很长我们不去爆破压缩包的密码,而是直接去直接爆破源文件的内容(一般都是可见的字符串),从而获取有效信息zip伪加密其实不是真的加密,只是修改了加密位数据包分析数据包分析,通常也被称为数据包嗅探或协议分析,指的是捕获和解析网络上在线传输数据的过程。数据包分析过程通常由数据包嗅探器来执行。而数据包嗅探器则是一种用来在网络媒介上捕获原始传输数据的工具。目前市面上有着多种类型的数据包嗅探器,包括免费的和商业的。每个软件的设计目标都会有一些差异。流行的数据包分析软件包括tcpdump、Wireshark等。Reverse逆向分析主要是将二进制机器码进行反汇编得到汇编代码,在汇编代码的基础上,进行功能分析。经过反编译生成的汇编代码中缺失了源代码中的符号、数据结构等信息,因此需要尽可能地通过逆向分析还原以上信息,以便分析程序原有逻辑和功能。逆向分析主要包括静态和动态分析。Pwn利用程序中的漏洞改变程序本来的执行流程Pwn在黑客俚语中代表着攻破,获得权限,由"own"这个词引申而来。在CTF比赛中它代表着溢出类的题目,常见的类型有整数溢出、栈溢出、堆溢出等。主要考察参赛选手对漏洞的利用能力。所需知识:C、OD+IDA、数据结构、操作系统。AWD对抗模式:AWD(attack with defence)攻防兼备模式,AWD模式是一个非常有意思的模式,你需要在一场比赛里扮演攻击方和防守方,攻击成功得分,失守也会扣除相应的分数。在比赛中,评分的关键点是flag,通过漏洞攻击敌方得到flag,可以获取相应的分数;反之,失守flag会被扣除相应的分数。从而模拟现实的网络攻击防御,以此提高选手的网络攻防能力。常见加固方法信息收集密码修改网站备份数据库备份后门查杀可疑服务和端口关闭源码审计漏洞验证漏洞修复文件监控WAF部署
2024年10月17日
1 阅读
0 评论
0 点赞
1
2