Защита приложения JS, созданного с помощью SAP Cloud SDK - PullRequest
1 голос
/ 06 апреля 2020

Я следую инструкциям на developer.sap.com для Javascript: Начало работы с SAP Cloud SDK для JavaScript.

Я создал свое приложение с:

sap-cloud-sdk init my-sdk-project

Теперь я хотел бы добавить к нему безопасность, в частности, я хочу использовать approuter для доступа к приложению и хочу заблокировать любой неаутентифицированный запрос к службе напрямую. При желании я хочу включить области действия для различных конечных точек моего приложения.

У меня нет проблем с добавлением approuter, но когда дело доходит до защиты приложения узла, я не могу найти правильный путь.

Я могу найти только примеры защиты приложения с помощью базовых c express приложений, таких как эти узлы:

Пример Hello World с использованием NodeJS

node.js Hello World

Но они имеют другую структуру, чем та, которая предоставляется инструментом sap-cloud-sdk, который использует nestjs. Справочный портал не указывает ни на один пример, если вы используете Nest js.

. Есть ли какой-либо ресурс, учебное пособие или пример, чтобы помочь мне реализовать безопасность в приложении с поддержкой скаффолдинга ?

Кр, кепаир

1 Ответ

2 голосов
/ 06 апреля 2020

Ресурс о том, как настроить безопасность Cloud Foun dry с Cloud SDK для JS, пока отсутствует, но в прошлом я немного повозился с ним, получив следующий результат.

Отказ от ответственности: Это ни в коем случае не готовый к использованию код! Пожалуйста, примите это только как вдохновение и проверьте все поведение на вашей стороне с помощью тестов, а также добавьте надежную обработку ошибок!

  1. Представьте файл scopes.decorator.ts со следующим содержанием:

    import { SetMetadata } from '@nestjs/common';
    
    export const ScopesMetadataKey = 'scopes';
    export const Scopes = (...scopes: string[]) => SetMetadata(ScopesMetadataKey, scopes);
    

    Это создаст аннотацию, которую вы можете добавить к своему методу контроллера на следующем шаге. Указанные параметры будут областями, которые требуются конечной точке перед вызовом.

  2. Создайте охрану scopes.guard.ts, как показано ниже:

    import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
    import { Reflector } from '@nestjs/core';
    import { retrieveJwt, verifyJwt } from '@sap/cloud-sdk-core';
    import { getServices } from '@sap/xsenv';
    import { ScopesMetadataKey } from './scopes.decorator';
    
    @Injectable()
    export class ScopesGuard implements CanActivate {
        private xsappname;
        constructor(private readonly reflector: Reflector) {
            this.xsappname = getServices({ uaa: { label: 'xsuaa' } }).uaa.xsappname;
        }
    
        async canActivate(context: ExecutionContext): Promise<boolean> {
            const scopes = this.reflector.get<string[]>(ScopesMetadataKey, context.getHandler());
            if (!scopes) {
                return true;
            }
    
            const request = context.switchToHttp().getRequest();
            const encodedJwt = retrieveJwt(request);
            if (!encodedJwt) {
                return false;
            }
    
            const jwt = await verifyJwt(encodedJwt);
            return this.matchScopes(scopes, jwt.scope);
        }
    
        private matchScopes(expectedScopes: string[], givenScopes: string[]): boolean {
            const givenSet = new Set(givenScopes);
            return expectedScopes.every(scope => givenSet.has(this.xsappname + '.' + scope));
        }
    }
    

    Этот охранник должен быть вызывается перед всеми конечными точками и проверяет, что во входящей JWT присутствуют все необходимые области.

  3. Добавьте защиту к настройке приложения гнезда:

    import { Reflector } from '@nestjs/core';
    import { ScopesGuard } from './auth/scopes.guard';
    
        // ...
        const app = ...
        const reflector = app.get(Reflector)
        app.useGlobalGuards(new ScopesGuard(reflector));
        // ...
    

    Это гарантирует, что все входящие запросы на самом деле «охраняются» вашим охранником, указанным выше.

  4. Используйте аннотацию, созданную на первом шаге для ваших конечных точек, достойных защиты:

    import { Controller, Get } from '@nestjs/common';
    import { Scopes } from '../auth/scopes.decorator';
    
    @Controller('/api/rest/foo')
    export class FooController {
        constructor(private readonly fooService: FooService) {}
    
        @Get()
        @Scopes('FooViewer')
        getFoos(): Promise<Foo[]> {
            return this.fooService.getFoos();
        }
    }
    

    Эта конечная точка теперь вызывается только при наличии JWT с необходимой областью действия.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...