保护使用SAP Cloud SDK构建的JS应用程序



我正在developers.sap.com上学习Javascript教程:开始使用SAP Cloud SDK for JavaScript。

我用创建了我的应用程序

sap-cloud-sdk init my-sdk-project

现在我想为它添加安全性,特别是,我想使用授权程序访问该应用程序,并且我想直接阻止任何未经验证的服务请求。可选地,我希望包括我的应用程序的不同端点的作用域。

我添加approxer没有任何问题,但当涉及到节点应用程序的安全时,我似乎找不到正确的方法。

我只能找到用基本的express节点应用程序保护应用程序的例子,比如

使用NodeJS 的Hello World示例

node.js Hello World

但它们与使用nestjssap-cloud-sdk工具提供的结构不同。如果您正在使用Nestjs,帮助门户也不会指向任何examplelet。

是否有任何资源、教程或示例可以帮助我在脚手架应用程序中实现安全性?

Kr,kepair

目前还没有关于如何使用Cloud SDK for JS设置Cloud Foundry安全性的资源,但我过去对它进行了一些修改,得到了以下结果。

免责声明:这绝不是可用于生产的代码!请仅以此为灵感,通过测试以及添加强大的错误处理来验证您的所有行为!

  1. 介绍一个包含以下内容的scopes.decorator.ts文件:

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

    这将创建一个注释,您可以在后续步骤中将其添加到控制器方法中。给定的参数将是端点在被调用之前所需的作用域。

  2. 创建一个Guardscopes.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));
    }
    }
    

    应在所有端点之前调用此Guard,并验证传入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时,才能调用此端点。

您可以在sapcloud-sdk/nest.js项目中使用标准的nodejs身份验证实现,而无需创建任何中间件。由于JWTStrategy是@sap/xssec的一部分,它有中间件实现,所以事情非常简化。

  1. 对于身份验证更改main.ts

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { getServices } from '@sap/xsenv';
const xsuaa = getServices({ xsuaa: { tag: 'xsuaa' } }).xsuaa;
import * as passport from 'passport';
import { JWTStrategy } from '@sap/xssec';
passport.use(new JWTStrategy(xsuaa));
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use(passport.initialize());
app.use(passport.authenticate('JWT', { session: false }));
await app.listen(process.env.PORT || 3000);
}
bootstrap();

这将初始化中间件。2.范围检查和授权

import { Controller, Get, Req, HttpException, HttpStatus } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) { }
@Get()
getHello(@Req() req: any): any {
console.log(req.authInfo);
const isAuthorized = req.authInfo.checkLocalScope('YourScope');
if (isAuthorized) {
return req.user;
} else {
return new HttpException('Forbidden', HttpStatus.FORBIDDEN);
}
// return this.appService.getHello();
}
}

有关更多详细信息,请参阅本

最新更新