MST

星途 面试题库

面试题:JavaScript 类和原型安全防护之高级题

在使用 ES6 类和传统原型方式创建对象时,分别阐述可能存在的安全风险,以及如何针对这些风险进行有效的安全防护,从属性访问控制、防止原型污染等方面详细说明。
16.5万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

ES6 类

  1. 安全风险
    • 属性访问控制:默认情况下,ES6 类的属性和方法是公开的,外部代码可以随意访问和修改,可能导致数据被非法篡改。例如:
class Example {
    constructor() {
        this.publicProperty = 'public data';
    }
}
let example = new Example();
console.log(example.publicProperty); // 外部可随意访问
example.publicProperty = 'new data'; // 外部可随意修改
- **原型污染**:虽然 ES6 类在一定程度上避免了传统原型链污染的常见问题,但如果在类的定义或实例化过程中,错误地操作原型对象,仍可能导致原型污染。比如通过直接修改 `Example.prototype` 并添加一些意外的属性,这些属性可能会影响到所有该类的实例。

2. 安全防护 - 属性访问控制:可以使用 JavaScript 的新提案 # 私有字段来实现属性的访问控制。例如:

class Example {
    #privateProperty = 'private data';
    getPrivateProperty() {
        return this.#privateProperty;
    }
}
let example = new Example();
// console.log(example.#privateProperty); // 报错,无法直接访问
console.log(example.getPrivateProperty()); // 通过内部方法访问私有属性
- **原型污染**:避免直接操作类的原型对象,尽量使用类的方法和属性来进行操作。如果确实需要扩展原型,要谨慎检查属性名,避免覆盖或添加意外的属性。

传统原型方式

  1. 安全风险
    • 属性访问控制:在传统原型方式中,属性和方法的访问控制非常薄弱。所有通过原型链共享的属性和方法对外部代码都是可访问和可修改的。例如:
function Example() {
    this.publicProperty = 'public data';
}
Example.prototype.getPublicProperty = function() {
    return this.publicProperty;
};
let example = new Example();
console.log(example.publicProperty); // 外部可随意访问
example.publicProperty = 'new data'; // 外部可随意修改
- **原型污染**:由于原型链的共享特性,很容易发生原型污染。恶意代码可以通过在原型对象上添加属性,影响到所有基于该原型创建的对象。例如:
function Example() {}
Example.prototype = {
    constructor: Example
};
// 恶意代码
Object.prototype.newMaliciousProperty = '恶意添加的属性';
let example1 = new Example();
let example2 = new Example();
console.log(example1.newMaliciousProperty); // 输出 '恶意添加的属性'
console.log(example2.newMaliciousProperty); // 输出 '恶意添加的属性'
  1. 安全防护
    • 属性访问控制:可以通过闭包和立即执行函数(IIFE)来模拟私有属性。例如:
let Example = (function() {
    let privateProperty = 'private data';
    function Example() {}
    Example.prototype.getPrivateProperty = function() {
        return privateProperty;
    };
    return Example;
})();
let example = new Example();
// console.log(privateProperty); // 报错,无法直接访问
console.log(example.getPrivateProperty()); // 通过内部方法访问私有属性
- **原型污染**:避免直接修改 `Object.prototype`,并且在扩展原型时,使用 `Object.defineProperty` 来精确控制属性的特性,确保不会意外地添加可枚举、可修改的属性。例如:
function Example() {}
Object.defineProperty(Example.prototype, 'newProperty', {
    value: '示例值',
    enumerable: false,
    writable: false,
    configurable: false
});
let example = new Example();
// 恶意代码无法轻易覆盖或枚举该属性