js逆向 - Proxy代理

    * */
    console.log(func)
    console.log(thisArg)
    console.log(argumentsList)
    return func.apply(thisArg, argumentsList);
}

}

let proxy = new Proxy(sum,handler)

console.log(proxy(1, 2));




### 三.  Proxy与Reflect基本使用



/*

  • Proxy作用: 监控对象操作
  • Reflect作用: 执行原始操作
  • */

let symbol = Symbol(123)

// 定义一个需要被代理的对象
let user = {
“name”:“小明”,
1:2,
[symbol]:“symbol111”
}

// 参数1: 需要代理的对象或函数等
// 参数2: 拦截器
let proxy = new Proxy(user,{
get:function (target, prop, receiver) {
/*
* target: 原始对象
* prop: 属性名,只有两种类型,string|symbol,其他传入的类型都会转为string类型
* receiver: 被代理后的对象
* */

    // 直接通过原始对象target[prop]获取属性值
    // 不会递归
    // let result = target[prop]

    // 通过Reflect.get(target, prop, receiver)获取属性值
    // 可以递归
    let result = Reflect.get(target,prop,receiver)
    console.log(`get方法 对象:${JSON.stringify(target)} 属性:${prop.toString()} 返回值:${result}`)

    // if (typeof prop=== 'string'){
    //     console.log(`get方法 对象:${JSON.stringify(target)} 属性:${prop} 返回值:${result}`)
    // }else if (typeof prop === "symbol"){
    //     // symbol不能使用模板字符串,不然会报错,所以这里做了一层判断
    //     console.log("正在获取: ",prop)
    // }

    return result
},
set:function (target, prop, newValue, receiver) {
    /*
    * target: 原始对象
    * prop: 属性名
    * newValue: 修改的值
    * receiver: 被代理后的对象
    * */
    console.log(`set方法 对象:${JSON.stringify(target)} 属性:${prop} 修改的值:${newValue}`)
    target[prop] = newValue
}

})

// 使用name属性时触发get方法
console.log(proxy.name);

// 设置name属性时触发set方法
proxy.name = “雷点1”

// ===================================

console.log(proxy[symbol])

// ===================================
console.log(proxy[1])

// ===================================
// 输出undefined,因为当前代理的对象中不存在这个属性,
// 在补环境中使用代理时,当一个属性或者方法被调用得到的结果是undefined时就需要去进行补环境
console.log(proxy.age)




### 四. 简单模拟proxy应用场景



let window = {

}

// 代理,window
window = new Proxy(window,{
get(target, p, receiver) {
let result = Reflect.get(target,p,receiver)
console.log(get方法 对象:${JSON.stringify(target)} 属性:${p.toString()} 返回值:${result})
return result
},
set:function (target, p, newValue, receiver) {
console.log(set方法 对象:${JSON.stringify(target)} 属性:${p.toString} 修改的值:${newValue})
target[p] = newValue
}
})

// 假设以下是抠出来的代码,然后调用href,但是href我们在window中没有定义,那么就会输出 返回值undefined,这时候我们就要去补这个href属性
// 根据调用的属性去当前目标网站根据控制台输出,拿到结果然后补到window身上,也可以使用脱环境的方式去拿到浏览器中的环境
console.log(window.href);


这时候window.href属性是undefined,我们就要去当前调试的目标网站将href属性抠出来补到window身上


**注:如果还不了解的话到后面会有实战案例,尽情期待!**




### 五. Proxy封装-1



function BrokerProxy(obj,objName){
/*
* obj: 需要代理的对象
* objName: 代理对象的名字
* 疑问点: 为什么还要传入对象的名字,因为不能直接通过对象来获取对象的名字,所以需要传进来
* /
return new Proxy(
obj,
{ // 拦截器方法
get(target, prop, receiver){
/

* target: 目标对象
* prop: 被获取的属性名
* receiver: 被代理后的对象
* /
let result = Reflect.get(target, prop, receiver) // 反射,执行原始的操作
console.debug(get方法: 对象: ${objName} 属性名: ${prop.toString()} 属性值: ${result})
return result
},
set(target, prop, value){
/

* target: 目标对象
* prop: 被修改的属性名
* value: 新属性值
* */
console.debug(set方法: 对象: ${objName} 设置的属性名: ${prop.toString()} 设置的属性值: ${value})
target[prop] = value
}
}
)
}

let symbol = Symbol(123)

let window = {
name:“雷点”,
true:2,
[symbol]:“symbol123”,
age:123
}

window = BrokerProxy(window,‘window’)
console.log(window.name);
window.name = “javascript”


代码解读:


1. 首先定义一个函数:BrokerProxy
2. BrokerProxy函数接收两个参数:obj,objName
	1. obj: 需要被代理的对象
	2. objName: 被代理对象的名称
3. 进入函数内部后,return new Proxy(obj,{get,set})  返回代理后的对象
	1. new Proxy(obj,{get,set})
		1. obj:当前被代理的对象
		2. get 拦截器方法:调用被代理对象的属性时触发
		3. set 拦截器方法:设置被代理对象的属性时触发
4. 在get拦截器方法中接收三个参数:target,prop,receiver
	1. target:目标对象
	2. prop: 被获取的属性名
	3. receiver:被代理后的对象
5. 在get拦截器中的操作:
	1. **通过Reflect.get() 执行原始操作,返回被获取的属性**
		1. let result = Reflect.get(target,prop,receiver)
	2. 日志输出:详细输出了,被调用的对象名,调用的属性名,属性值
		1. console.debug(`get方法: 对象: ${objName} 属性名: ${prop.toString()} 属性值: ${result}`)
6. 在set拦截器方法中接收三个参数:target,prop,value
	1. target:目标对象
	2. prop: 被设置的属性名
	3. value:新属性值你
7. 在set拦截器中的操作
	1. 日志输出:详细输出了,被设置的对象名,设置的属性名,设置的值
		* console.debug(`set方法: 对象: ${objName} 设置的属性名: ${prop.toString()} 设置的属性值: ${value}`)
8. 走到函数外部:
	* 定义了一个window对象:window = BrokerProxy(window,'window')
	* **在window对象加载后使用自定义封装的BrokerProxy函数对window进行代理,返回被代理后的window对象**
	* **通过返回被代理的window对象**获取name操作:console.log(window.name); 这时候就会触发 拦截器方法get方法,并且执行get方法里面的操作
	* 通过返回被代理的window对象设置name操作:window.name = "javascript"; 这时候就会触发 拦截器方法set,并且执行set方法里面的操作



### 六. Proxy封装-2


关于proxy封装的第二篇不在做多余的讲解,**详细的注释已经在代码中写上**,如果还不了解可以前往:[Proxy() 构造函数 - JavaScript | MDN]( ) 构造函数 - JavaScript | MDN") 进一步详细的了解



/*

  • 代理器方法封装
  • */

function getType(obj){
return Object.prototype.toString.call(obj)
}

function BrokerProxy(obj,objName){
/*
* obj: 需要代理的对象
* objName: 代理对象的名字
* 疑问点: 为什么还要传入对象的名字,因为不能直接通过对象来获取对象的名字,所以需要传进来
* /
return new Proxy(
obj,{
// 用于拦截对象的 获取值的 操作
get(target, prop, receiver){
/

* target: 目标对象
* prop: 被获取的属性名
* receiver: 被代理后的对象
* */
let result;
try{
result = Reflect.get(target, prop, receiver) // 反射,执行原始的操作
let type = getType(result)
if(result instanceof Object){
console.debug(get方法[获取]: ${objName}.${prop.toString()} [属性值]: ${JSON.stringify(result)} [类型]:${type} )
// 如果属性是一个对象的话就进行递归代理
result = BrokerProxy(result,${objName}.${prop.toString()})
}else if(typeof result === “symbol”){
console.debug(get方法[获取]: ${objName}.${prop.toString()} [属性值]: ${result.toString()})
}else{
console.debug(get方法[获取]: ${objName}.${prop.toString()} [属性值]: ${result})
}
}catch (e) {
console.error(get方法[获取]: 对象: ${objName} [属性]:${prop.toString()} [错误信息]: ${e.message})
}
return result
},

        // 用于拦截对象的 设置值的 操作
        set(target, prop, value){
            /*
            * target: 目标对象
            * prop: 被修改的属性名
            * value: 新属性值
            * */
            // 使用 Reflect.set
            try{
                 let success = Reflect.set(target, prop, value);
                 let type = getType(value)
                 if(value instanceof Object){
                     console.debug(`set方法[设置]: ${objName}.${prop.toString()} [设置的属性值]: ${JSON.stringify(value)} [类型]: ${type}`)
                 }else if (typeof value === "symbol"){
                      console.debug(`set方法[设置]: ${objName}.${prop.toString()} [设置的属性值]: ${value.toString()}`)
                 }else{
                     console.debug(`set方法[设置]: ${objName}.${prop.toString()} [设置的属性值]: ${value}`)
                 }
            }catch (e) {
                console.error(`设置属性失败: ${objName}.${prop.toString()}`);
            }
        },

        // 用于拦截对象的 Object.getOwnPropertyDescriptor() 的操作
        // Object.getOwnPropertyDescriptor() 方法,用于获取属性描述符信息
        getOwnPropertyDescriptor(target, prop) {
            /*
            * target: 目标对象
            * prop: 需要返回属性名称的描述符的,属性名
            * getOwnPropertyDescriptor 方法必须返回一个 object 或 undefined。
            * */
            try {
                result = Reflect.getOwnPropertyDescriptor(target, prop)
                if (typeof result !== "undefined"){
                    console.debug(`getOwnPropertyDescriptor方法[获取属性描述符]: ${objName}.${prop.toString()} [获取属性描述符]: ${JSON.stringify(result)}`)
                    // result = BrokerProxy(result,`${objName}.${prop.toString()}`)
                }else{
                    console.debug(`getOwnPropertyDescriptor方法[获取属性描述符]: ${objName}.${prop.toString()} [获取属性描述符]: ${JSON.stringify(result)} [提示]: ${prop.toString()}属性不存在`)
                }
            }catch (e) {
                console.error(`getOwnPropertyDescriptor方法[获取属性描述符]: 对象: ${objName} [获取属性描述符]:${prop.toString()} [错误信息]: ${e.message}`)
            }
            return result
        },

        // 用于拦截对象的 Object.defineProperty() 操作
        // Object.defineProperty() 方法,用于设置属性描述符信息
        defineProperty(target, prop, descriptor) {
           /*
            * target: 目标对象
            * prop: 需要修改属性描述符的,属性名称
            * descriptor: 需要重新定义属性描述符对象
            * */
            try {
                let result = Reflect.defineProperty(target, prop, descriptor);
                console.debug(`defineProperty方法[设置属性描述符]: ${objName}.${prop.toString()} [设置的属性描述符]: ${JSON.stringify(descriptor)}`)
            }catch (e) {
                console.error(`defineProperty方法[获取属性描述符]: 对象: ${objName} [设置属性描述符]:${prop.toString()} [错误信息]: ${e.message}`)
            }
            return result
        },

        // 当代理的对象是一个函数时,返回的函数对象触发apply方法
        // 或当调用对象中的属性值是一个函数时,触发apply方法
        apply(target, thisArg, argArray) {
            /*
            * target: 目标对象
            * thisArg: 被调用时的上下文对象
            * argArray: 被调用时的参数数组,例如:[2,3]
            * */
            let result
            try {
                result = Reflect.apply(target, thisArg, argArray)
                // console.debug(`apply方法[调用函数]: ${objName} [函数参数]: ${argArray} [返回结果]: ${JSON.stringify(result)}`)
                if (result instanceof Object){
                    console.debug(`apply方法[调用函数]: ${objName} [返回结果]: ${JSON.stringify(result)}`)
                }else if (typeof result === "symbol"){
                    console.debug(`apply方法[调用函数]: ${objName} [返回结果]: ${result.toString()}`)
                }else{
                    console.debug(`apply方法[调用函数]: ${objName} [返回结果]: ${result}`)
                }
            }catch (e) {
                console.error(`apply方法[调用函数]: ${objName} [函数参数]: ${argArray} [错误信息]: ${e.message}`)
            }
            return result
        },

        // construct 方法用于拦截 new 操作符
        construct(target, argArray, newTarget) {
             /*
            * target: 目标对象
            * argArray: constructor 的参数列表。
            * newTarget: 代理后的对象
            * */
          let result
            try {
                result = Reflect.construct(target, argArray, newTarget)
                let type = getType(result)
                console.debug(`construct方法[new ${objName}]: ${objName} [类型]: ${type}`)
            }catch (e) {
                console.error(`construct方法[new ${objName}]: ${objName} [错误信息]: ${e.message}`)
            }
            return result
        },

        // 拦截对象自身属性的 delete 操作
        // 当对对象某个属性进行删除: delete user.name 时触发
        deleteProperty(target, prop) {
            /*
            * target: 目标对象
            * prop: 要进行delete操作的属性名
            * */
            let result = Reflect.deleteProperty(target,prop)
            console.debug(`deleteProperty方法[删除]: delete ${objName}.${prop} [是否可删除]: ${result}`)
            return result
        },

        // 当对自身属性进行遍历时触发
        ownKeys(target) {
            /*
            * target: 目标对象
            * */
            let result = Reflect.ownKeys(target)
            console.debug(`ownKeys方法[正在属性遍历的对象]: ${objName}`)
            return result
        },

        // 当获取代理对象的原型时,触发
        // 对象.__proto__时触发
        // 或 Object.getPrototypeOf 时触发
        getPrototypeOf(target) {
            /*
            * target: 目标对象
            * */
            let result = Reflect.getPrototypeOf(target)
            console.debug(`getPrototypeOf方法[获取原型对象] ${objName}.__proto__`)
            return result
        },

        // 当Object.setPrototypeOf设置对象原型时,触发
        setPrototypeOf(target, value) {
            /*
            * target: 目标对象
            * value: 要设置的值
            * */
            let result = Reflect.setPrototypeOf(target,value)
            console.debug(`setPrototypeOf方法 [设置原型对象] ${objName}.__proto__ = [设置内容]: ${value}`)
            return result
        }
    }
)

}

let window = {
name:“雷点”,
info:{
name:“小红”,
age:10,
info2:{
name:“红”,
age:10,
}
},
add:function (a, b) {
return a + b
}
}

// 代理的使用: 需要在window对象加载后使用
window = BrokerProxy(window,‘window’)

console.log(“get方法=====”)

window.name
window.info.name
window.info.info2.name

console.log(“set方法=====”)

window.name = “javascript”
window.clas = {name:“小星星”}
window.clas
window.clas.name

console.log(“getOwnPropertyDescriptor方法=====”)

// 获取window对象的name属性操作符时,触发getOwnPropertyDescriptor拦截器
// 当获取的是一个不存在的属性时,得到的属性描述符结果是一个: undefined
// Object.getOwnPropertyDescriptor(window,“aaaaaaaaaaa”)

// 当获取的是存在的属性时,得到的属性描述符结果是对应的描述符信息: {“value”:“javascript”,“writable”:true,“enumerable”:true,“configurable”:true}
Object.getOwnPropertyDescriptor(window,“name”)

console.log(“defineProperty方法=====”)

// 当window给name属性设置属性描述符的时候触发 defineProperty拦截器
Object.defineProperty(window,“name”,{
writable:false,
configurable:true,
value:“设置属性值”
})

console.log(“apply方法=====”)

// 情况1: 当调用的是window对象中的函数时,触发apply方法
window.add(10,20)

// 情况2: 单独代理的是一个函数时,调用函数,触发apply方法
function add2(a,b) {
return a * b
}

add2 = BrokerProxy(add2,“add2”)
add2(100,200)

function add3(a,b) {
return a
}
add3 = BrokerProxy(add3,“add3”)
add3({“name”:“小红”},200)
add3(Symbol(),200)

最后

小编综合了阿里的面试题做了一份前端面试题PDF文档,里面有面试题的详细解析

虽只说了一个公司的面试,但我们可以知道大厂关注的东西并举一反三,通过一个知识点延伸到另一个知识点,这是我们要掌握的学习方法,小伙伴们在这篇有学到的请评论点赞转发告诉小编哦,谢谢大家的支持!

京东JS逆向403错误通常是由于请求被服务器拒绝或者被检测到了异常行为导致的。根据提供的引用内容,我们可以看到代码中使用了execjs库来执行JavaScript代码,并且调用了getPwd函数进行密码加密。这种逆向行为可能违反了京东的使用条款,因此服务器会返回403错误。 为了解决这个问题,你可以尝试以下几点: 1. 模拟正常的浏览器行为:在请求中添加合适的User-Agent和Referer头部,使请求看起来更像是来自正常的浏览器。 2. 使用合适的代理:使用代理服务器可以隐藏你的真实IP地址,减少被检测到的风险。 3. 降低请求频率:如果你的请求频率过高,可能会被服务器认为是恶意行为。可以适当调整请求的频率,避免被封禁。 4. 分析和修改代码:仔细分析代码中的逻辑,尝试找到可能触发403错误的地方,并进行相应的修改。 需要注意的是,逆向工程和绕过网站的安全措施是违反法律和道德规范的行为。在进行任何逆向行为之前,请确保你有合法的授权,并遵守相关法律法规。 #### 引用[.reference_title] - *1* *2* [京西js逆向](https://blog.csdn.net/T_I_A_N_/article/details/121889686)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [js逆向_极验3代滑块(js协议逆向)](https://blog.csdn.net/hdd706/article/details/125453838)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值