fontcolor_theme
Deepkit RPC

Sicherheit

Standardmäßig können alle RPC-Funktionen von jedem Client aufgerufen werden, und die Peer-to-Peer-Kommunikation ist aktiviert. Um präzise zu steuern, welcher Client was darf, können Sie die Klasse RpcKernelSecurity überschreiben.

import { RpcKernelSecurity, Session, RpcControllerAccess } from '@deepkit/type';

//enthält Standardimplementierungen
class MyKernelSecurity extends RpcKernelSecurity {
    async hasControllerAccess(session: Session, controllerAccess: RpcControllerAccess): Promise<boolean> {
        return true;
    }

    async isAllowedToRegisterAsPeer(session: Session, peerId: string): Promise<boolean> {
        return true;
    }

    async isAllowedToSendToPeer(session: Session, peerId: string): Promise<boolean> {
        return true;
    }

    async authenticate(token: any): Promise<Session> {
        throw new Error('Authentication not implemented');
    }

    transformError(err: Error) {
        return err;
    }
}

Um dies zu verwenden, übergeben Sie den Provider an den RpcKernel:

const kernel = new RpcKernel([{provide: RpcKernelSecurity, useClass: MyKernelSecurity, scope: 'rpc'}]);

Oder überschreiben Sie im Fall einer Deepkit-App die Klasse RpcKernelSecurity mit einem Provider in der App:

import { App } from '@deepkit/type';
import { RpcKernelSecurity } from '@deepkit/rpc';
import { FrameworkModule } from '@deepkit/framework';

new App({
    controllers: [MyRpcController],
    providers: [
        {provide: RpcKernelSecurity, useClass: MyRpcKernelSecurity, scope: 'rpc'}
    ],
    imports: [new FrameworkModule]
}).run();

Authentifizierung / Session

Standardmäßig ist das Session-Objekt eine anonyme Session, d. h. der Client hat sich nicht authentifiziert. Wenn der Client sich authentifizieren möchte, wird die Methode authenticate aufgerufen. Das von der Methode authenticate empfangene Token kommt vom Client und kann jeden beliebigen Wert haben.

Sobald der Client ein Token setzt, wird die Authentifizierung ausgeführt, wenn die erste RPC-Funktion aufgerufen wird oder wenn client.connect() manuell aufgerufen wird.

const client = new RpcWebSocketClient('localhost:8081');
client.token.set('123456789');

const controller = client.controller<Controller>('/main');

In diesem Fall erhält RpcKernelSecurity.authenticate das Token 123456789 und kann entsprechend eine andere Session zurückgeben. Die zurückgegebene Session wird dann an alle anderen Methoden wie hasControllerAccess weitergegeben.

import { Session, RpcKernelSecurity } from '@deepkit/rpc';

class UserSession extends Session {
}

class MyKernelSecurity extends RpcKernelSecurity {
    async hasControllerAccess(session: Session, controllerAccess: RpcControllerAccess): Promise<boolean> {
        if (controllerAccess.controllerClassType instanceof MySecureController) {
            //MySecureController erfordert UserSession
            return session instanceof UserSession;
        }
        return true;
    }

    async authenticate(token: any): Promise<Session> {
        if (token === '123456789') {
            //Benutzername kann eine ID oder ein Benutzername sein
            return new UserSession('username', token);
        }
        throw new Error('Authentication failed');
    }
}

Controller-Zugriff

Die Methode hasControllerAccess bestimmt, ob ein Client eine bestimmte RPC-Funktion ausführen darf. Diese Methode wird bei jedem Aufruf einer RPC-Funktion ausgeführt. Gibt sie false zurück, wird der Zugriff verweigert und beim Client ein Fehler ausgelöst.

Das RpcControllerAccess enthält wertvolle Informationen über die RPC-Funktion:

interface RpcControllerAccess {
    controllerName: string;
    controllerClassType: ClassType;
    actionName: string;
    actionGroups: string[];
    actionData: { [name: string]: any };
}

Gruppen und zusätzliche Daten können über den Decorator @rpc.action() geändert werden:

class Controller {
    @rpc.action().group('secret').data('role', 'admin')
    saveUser(user: User): void {
    }
}

class MyKernelSecurity extends RpcKernelSecurity {
    async hasControllerAccess(session: Session, controllerAccess: RpcControllerAccess): Promise<boolean> {
        if (controllerAccess.actionGroups.includes('secret')) {
            if (session instanceof UserSession) {
                //todo: prüfen
                return session.username === 'admin';
            }
            return false;
        }
        return true;
    }
}
English中文 (Chinese)한국어 (Korean)日本語 (Japanese)Deutsch (German)