跳到内容
技术文章
作者简介照片Cha万博新体育手机客户端im Bendelac

第3部分:使用真实数据验证的安全SAP图

你好!

这是SAP图表中开发人员教程的第三部分,SAP集成智能套件的API。请参阅第1部分本教程介绍SAP图表,到第2部分介绍了SAP Graph的编程接口,以及地图的信息介绍整个教程系列。

在本教程的第3部分中,我们将建立古典企业扩展Web应用程序的基本基础:a列表详细信息导航应用程序。

SAP图租户

第2部分,我们从一个预配置的SAP Graph租户访问数据,该租户用于通过SAP API Business Hub访问沙箱数据。我们甚至将这个服务器URL嵌入到代码中。任何拥有API密钥的人都可以访问沙箱数据,而无需任何进一步的身份验证或授权。

当然,这不是访问机密业务数据的安全方式。因此,在本教程的这一部分,我们将通过oAuth协议安全地访问SAP Graph。OAuth不共享密码数据,而是使用授权令牌来证明客户端和服务(如SAP Graph)之间的身份,并支持单点登录。有了oAuth,您可以有效地批准您的浏览器与SAP Graph交互,而无需放弃您的密码。

SAP图是一个多租户服务。客户管理员使用SAP业务技术平台(BTP)到订阅SAP Graph,通过配置一个或多个SAP图租户.我们将在本教程的后面部分更详细地讨论这个主题,但是此时,理解这个SAP Graph租户是特定的关键是很重要的景观客户系统。大多数客户将配置多个场景,例如用于开发、分段和生产使用。

每个SAP图租户都是唯一的凭据,例如租户特定的URL和各种秘密/令牌。

credentials.js.

要以编程方式从SAP Graph租户访问数据,应用程序需要这些凭据。你是怎么得到它们的?一个包含它们的文件,credentials.json.,是在设置和配置SAP图租户的过程中创建的。您从BTP管理员收到此文件,该管理员配置了要访问的特定SAP图形租户。

保存文件src文件夹的项目(您可以使用现有的src我们在里面开发了第一个你好图形服务器端应用程序,或在项目中创建一个新的源文件夹,由您提供)。

注意:如果您对执行本教程感兴趣,并且没有访问您自己的SAP管理数据源的权限,请与SAP Graph团队联系sap.graph@sap.com..根据您的要求,在一定的时间内,我们可以为您提供证件。使用预配置的SAP Graph租户访问数据集。

auth.js.

在相同的src文件夹,创建一个名为auth.js.,粘贴以下样品板(标准)代码,并保存:

Const credentials = require("./credentials.json");Const fetch = require("node-fetch");const cookie = require("universal-cookie");const CALLBACK_URI = "/myCallbackURI";const CookieName = "SAPGraphHelloQuotesCookie";class Auth {constructor() {this。clientId = credentials.uaa.clientid;这一点。clientSecret = credentials.uaa.clientsecret;这一点。authUrl = credentials.uaa.url; } getToken(req) { const cookies = new Cookies(req.headers.cookie); return cookies.get(CookieName); } async fetchToken(code, redirectUri) { const params = new URLSearchParams(); params.set('client_id', this.clientId); params.set('client_secret', this.clientSecret); params.set('code', code); params.set('redirect_uri', redirectUri); params.set('grant_type', 'authorization_code'); const response = await fetch(`${this.authUrl}/oauth/token`, { method: 'post', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json' }, body: params }); const json = await response.json(); return json.access_token; } getMiddleware() { return async (req, res, next) => { const redirectUri = `${req.protocol}://${req.get("host")}${CALLBACK_URI}`; if (req.url.startsWith(CALLBACK_URI)) { const code = req.query.code; if (code) { const token = await this.fetchToken(code, redirectUri); res.cookie(CookieName, token, { maxAge: 1000 * 60 * 120, httpOnly: true, path: "/", }); } res.redirect("/"); } else if (!this.getToken(req)) { res.redirect(`${this.authUrl}/oauth/authorize?client_id=${encodeURIComponent(this.clientId)}&redirect_uri=${encodeURIComponent(redirectUri)}&response_type=code`); } else { next(); } }; } } module.exports = Auth;

如您所见,这种样板身份验证码指的是从中提取的几条信息credentials.json.根据SAP Graph租户的具体情况,使用单点登录来登录您的应用程序的用户。为了方便用户,它还将获得的访问令牌保存为cookie,以便在过期之前可以使用。

graph.js

我们将重用我们在其中看到的Graph类第2部分在本教程中,但是,现在我们必须在我们使用SAP图租户之前验证用户,我们需要进行一些小的变化。将以下文本复制到graph.js并保存。

Const fetch = require("node-fetch");Const credentials = require("./credentials.json");const apiurl = credentials.uri;const apiverion =“v1”;类图{构造函数(auth){this.auth = auth;this.apiurl = apiurl;这个.apiorsion = apiersion;} Async get(req,实体,params){const令牌= this.auth.getToken(REQ);const url =`$ {this.apiurl} / $ {this.apirsion} / $ {entity} $ {params?`?$ {params}`:“”}`; console.log(url) //for debugging const options = { method: "get", headers: { "Authorization": `Bearer ${token}`, "Accept": "application/json" } }; const response = await fetch(url, options); console.log(`${response.status} (${response.statusText})`) // for debugging const json = await response.json(); return json; } } module.exports = Graph;

你可以看到我们做了两个小变化。现在,SAP图形URL从特定SAP图形租户的凭据确定,并且在用户身份验证期间获得的授权令牌将传递给SAP图形。

helloquotes.js.

现在我们终于准备建立了古典三页企业扩展Web应用程序的基本基础:alist-details-navigate应用程序.这是最终的样子:

不要指望花哨的代码,具有强大的生产准备应用程序的所有必要错误和异常处理。我们的目标是展示只需使用SAP图形创建小型业务应用程序的容易;我们将在本教程的另一部分讨论强大的SAP图表客户端的更精细方面。

我们将首先在我们呼叫的文件中建立我们的应用程序的骨架helloquotes.js.

// Hello Quote -我们的第一个SAP图形扩展应用程序const express = require("express");const Graph = require("./ Graph ");const Auth = require("./ Auth ");Const app = express();Const port = 3003;const auth = new auth ();app.use (auth.getMiddleware ());const graph = new graph (auth);// ------------------ 1)获取和显示CustomerQuotes的列表  ------------------ // ------------------ 2)显示一个报价和项目  ------------------ // ------------------ 3)导航到产品细节的所有项目的报价  ------------------ app.listen(端口、() => {console.log('示例应用程序监听http://localhost:${port} ')});

这段代码没有做任何有趣的事情。它使用我们刚才讨论的标准身份验证登录用户,然后在端口3003上监听web (REST)请求。要使代码工作,我们需要安装请求处理程序

使用表示框架,我们现在创建三个这样的处理程序,对应三个不同的预期网址:

  1. 根(/)
  2. 请求Quote:/ quote / ...
  3. 请求报价的产品详情:/ Quote ... /产品

下面是第一个请求处理程序:

// ------------------ 1)获取和显示CustomerQuotes的列表  ------------------ app.get(' / ',异步(点播,res) = >{常量引用=等待图。get (sap.odm要求。”销售/ CustomerQuote”、“顶级= 20美元”);Const qlist = quotes.value。(q => ' 

${q。effectiveDate}(${问。totalAmount}美元)< / p >”). join (" ");res.send('

Hello Quotes

${qlist} ');});

如果浏览器请求根文档(“/”),将解雇处理程序。代码是什么?它获取了前20个引号(sap.odm.sales / CustomerQuote),然后在HTML中包装结果(日期和总量),并返回它。

继续,将此处理程序粘贴到App Skeleton,保存,并在终端控制台上运行服务器端应用程序,如下所示:

节点helloQuotes.js

打开一个新的浏览器选项卡,并输入URL http://localhost:3003。如果一切顺利,您现在将在浏览器中看到日期和相应数量的列表。

那很好,但不是很有趣。将您的应用程序转换为一个有趣的列表详细信息应用程序,修改qlist在上面的任务介绍一个链接, 如下:

const qlist = quees.value.map(q =>`

/报价......'。现在让我们介绍我们的第二和第三个处理程序:

// ------------------ 2)显示一个报价和项目  ------------------ app.get(' /报价/:id,异步(点播,res) = > {const id = req.params.id;const singleQuote = await graph。get(点播,sap.odm.sales CustomerQuote / $ {id} ',“扩大=项目选择美元=项目”);res.send(' 

Customer Quote - Detail

id: ${id}
${JSON.stringify(singleQuote,null,2)}
');});// ------------------ 3)导航到产品细节的所有项目的报价 ------------------ app.get(/报价/:id /产品,异步(点播,res) = > {const id = req.params.id;const singleQuote = await graph。get(点播,sap.odm.sales CustomerQuote / $ {id} ',“扩大美元=物品(扩大美元=产品(选择美元= displayId)) & $选择=项目”);const productIds = singleQuote.items。地图(i = > i.product.displayId);const filterClause = productIds。map(p => ' displayId eq '${p}' ')。加入(”和“); const products = await graph.get(req, `sap.odm.product/Product`,`$filter=${filterClause}`); res.send(`

Products for Customer Quote

id: ${id}

${JSON.stringify(products,null,2)}
`); });

第二个处理程序核心的ODATA查询使用$扩展查询参数以获取报价的详细信息,包括引用的内容(项目)。然后在第三个处理程序中使用报价中的产品ID导航在业务图中,从产品目录获取详细的产品信息。在这两种情况下,数据刚刚将屏幕转储为JSON,但显然,真实的应用程序将更好地格式化信息。

继续,在第一个处理程序中进行更改,然后将第二个和第三个处理程序粘贴到代码中,保存文件,重新启动服务,并刷新localhost:3003浏览器的页面。瞧!您的应用程序就在于。

再次注意,作为开发人员,您从来不必问自己数据来自哪里。您只需从报价对象导航到产品对象,无需任何努力。您通过已配置的SAP Graph租户访问的环境可能在SAP Sales Cloud或SAP S/4HANA中管理报价,而产品目录理论上可能在另一个系统中。你根本不必在意。


Chaim Bendelac,首席产品经理- SAP Graph

请访问SAP Graph网站http://explore.graph.sap/

联系我们在sap.graph@sap.com.


/
成为第一个评论者
你一定是登录评论评论或回复一篇文章