使用类属性作为键时,“此操作不安全”

时间:2016-09-10 15:41:16

标签: dictionary angular typescript

我有一个自定义FileArgument类,我用它来存储有关上传文件的信息:

export class FileArgument {
  name: string;
  path: string;
  file: File;
}

我的上传工作正常,然后服务器返回文件上传的路径。然后,我想使用先前设置的fileArgument.name作为键将此路径存储在字典中。以下是我的组件的简要概述。 onSubmit()是行动发生的地方:

export class InputModuleComponent {
    private vsmodule: InputModule;
    private moduleArguments = {};
    private fileArgument: FileArgument = new FileArgument();

    @Input()
    module: InputModule;

    constructor(private inputModuleService: InputModuleService) {}

    onSubmit(): void {
        this.inputModuleService.postFile(this.fileArgument.file).subscribe(
            response => {
                this.moduleArguments[this.fileArgument.name] = response.filename;
                console.log(this.moduleArguments);
            },
            error => {}
        );
    }

    onFileChange(event): void {
        this.fileArgument.file = event.originalTarget.files[0];
        this.fileArgument.name = event.originalTarget.id;
    }
}

上面的第14行(this.moduleArguments[this.fileArgument.name] = response.filename;)会在Firefox中导致以下错误:

EXCEPTION: Uncaught (in promise): SecurityError: The operation is insecure.

并在Chrome中:

core.umd.js:5995 EXCEPTION: Uncaught (in promise): InvalidStateError: Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string.

如果我用例如:

替换该行
this.moduleArguments['hello'] = response.filename;

我没有收到任何错误。错误显然来自于使用fileArgument.name作为dict键,但我不明白为什么。

编辑:我的服务中的postFile()方法如下:

postFile (file: File): Observable<any> {
    console.log('input-module.service - postFile()');
    var url = this.uploadURL;

    return Observable.create(observer => {
        var formData: FormData = new FormData()
        var xhr: XMLHttpRequest = new XMLHttpRequest();

        formData.append("upload", file, file.name);

        xhr.onreadystatechange = () => {
            if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                    observer.next(JSON.parse(xhr.response));
                    observer.complete();
                } else {
                observer.error(xhr.response);
                }
            }
        };

        xhr.open('POST', url, true);
        xhr.send(formData);
    });
}

组件HTML:

<a (click)="modal.open()">
    {{vsmodule.displayName}}
</a>

<modal #modal>
    <form (ngSubmit)="onSubmit()">
        <modal-header [show-close]="true">
            <h4 class="modal-title">Input Module - {{vsmodule.displayName}}</h4>
        </modal-header>

        <modal-body>
            <p>{{vsmodule.description}}</p>
            <hr>
                <ul>
                    <li *ngFor="let arg of vsmodule.args; let i = index">
                        <fieldset *ngIf="arg.type == 'file'">
                            <label>{{ arg.displayName }}</label>
                            <input 
                                name="{{arg.name}}" 
                                id="{{ arg.name }}"
                                type="file"

                                [(ngModel)]="moduleArguments[arg.name]"
                                (change)="onFileChange($event)" 
                            >
                            <p>{{ arg.description }}<p>
                        </fieldset>
                    </li>
                </ul>
        </modal-body>

        <modal-footer>
            <button type="button" class="btn btn-default" data-dismiss="modal" (click)="modal.dismiss()">Dismiss</button>
            <button type="submit" class="btn btn-primary">Run</button>
        </modal-footer>
    </form>
</modal>

3 个答案:

答案 0 :(得分:3)

onChange中,fileArgument.name设置为event.originalTarget.id的值 - 页面中实际HTML元素的ID

Chrome错误说:

Failed to set the 'value' property on 'HTMLInputElement'

编辑,因为您添加了html - 您已将'moduleArguements'属性绑定到文件输入元素的ngmodel - 因此,更改该值将导致angular尝试修改文件输入上的value属性,这是不允许的

更新该值的目的是什么?它只是向用户反馈吗?

如果从输入元素中删除ngModel绑定它应该可以工作 - 你正在使用onFileChange事件来捕获新的文件名(尽管在控制器中它只是onChange?)

答案 1 :(得分:0)

简答:您无法实际更改this.moduleArguments[this.fileArgument.name]的值,因为这会是一个安全问题。

解释:您会将this.fileArgument.name的实际更改为其他内容,这会让其他有意图的人也这样做。实质上,攻击者可以更改该名称以将任何尝试将该文件重定向到另一个文件。因此,由于安全原因,Java(或Flash或任何其他编程语言)无法以编程方式更改它。

通过解决方法,您实际上并未设置File数据成员,因此JS不会将此视为安全隐患。

请记住,[几乎]你可以做的任何涉及网站/服务器代码(或代码与之交互的代码),攻击者也可以这样做。这就是为什么JS在这种情况下会阻止人们更改此特定标准File对象的内容。希望这有帮助!

答案 2 :(得分:0)

你尝试过这个:

var fileName = this.fileArgument.name;
this.moduleArguments[fileName] = response.filename;

如果你在JS的某个地方改变了“价值”。你的 标签,您将收到该错误,请参阅: https://stackoverflow.com/a/29721020/2071008