身份验证和授权¶
本节介绍 MindSphere 平台中有关身份验证和授权的最重要内容。本简介旨在帮助您在使用 MindSphere API 时能够快速启动和运行。 阅读本简介后,您将能够执行以下操作:
- 通过 Cloud Foundry 应用调用 MindSphere API。
- 通过前端应用调用 MindSphere API(例如通过 JavaScript 调用 AJAX)。
- 根据应用特定范围保护应用的安全。
简介¶
所有 MindSphere 端点都受到安全保护,只有身份验证成功后才能与之连接。之后,您将通过本简介中描述的不同方法获取一个令牌。 该令牌将包含允许您执行哪些操作等信息,例如,允许您使用哪些 API。
获取通过您的应用调用 MindSphere API 的令牌¶
如果要通过您的应用调用 MindSphere API,需要有一个有效的令牌。
先决条件¶
在MindSphere中运行应用程序
- 有关如何部署,注册和启用对应用程序的访问,参考 Running a Cloud Foundry-Hosted Application.
- 有关访问MindSphere API所需角色和范围的信息, 参考 角色和范围.
您的应用程序需要一个有效的令牌来调用MindSphere api。如果有登录用户通过 launchpad 或通过直接调用应用 URL 访问您的应用,则会有一个 令牌(bearer 类型的令牌)以消息头的形式传递到应用请求中。
两种通过应用调用 MindSphere API 的方法:
- 使用
gateway.{region}.{mindsphere-domain}/api/...
从后端(例如 Cloud Foundry)调用 API。 - 从前端调用 API,类似于
{webAppHost}/api/...
从后端调用 API¶
从后端调用 MindSphere API 时,每个请求都需要发送一个 authorization 消息头。因此,您需要将该请求中的请求头信息提取到后端,然后在您的 MindSphere API 请求中使用 authorization
消息头。
Java¶
以下 Java 代码段打印出所有可用消息头并返回令牌。
private String extractToken(HttpServletRequest request) {
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String header = headerNames.nextElement();
LOGGER.info("header " + header + " " + request.getHeader(header));
}
return request.getHeader("authorization");
}
令牌日志
生产代码中不输出任何类似令牌的机密日志!
当发送请求调用 重要 Urls部分列出的MindSphere APIs时,将令牌加入authorization
消息头。
Node.js¶
可以在 Node.js 中执行类似的操作。下面的简单示例使用 expressjs 和 superagent 进行 API 调用 - 将第 7 行中的 {region}
替换为您自己的区域。 以下Node.js代码段使用 expressjs 和 superagent 进行API调用 - 第7行包含占位符 region and MindSphere domain.
var request = require("superagent");
...
app.get('my-route', function (req, res) {
authHeader = req.get("authorization");
request
.get('https://gateway.{region}.{mindsphere-domain}/api/identitymanagement/v3/Users?attributes=meta,name,userName,active')
.set('Authorization', authHeader)
.set('Accept', 'application/json')
.then(function(data) {
res.json({
resources:data.body.resources
});
}).catch(err => {
console.error(err.message, err.status);
res.status(err.status).json({ message:'Failed to fetch users.'});
});
});
...
从前端调用 API¶
从前端调用 API时,不再发送 authorization
消息头,而是重新使用设置为 cookie 的 sessionid
,并发送由 MindSphere 网关作为cookie提供(例如 x-xsrf-token:e4edcb6c-bd1c-46c1-863c-421235c522a3
)的消息头:
x-xsrf-token:{XSRF-TOKEN}
下面显示的是一个使用 Fetch API 的示例:
let myXRSFToken = ...
fetch('/api/identitymanagement/v3/Users', {
credentials: 'include',
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
"x-xsrf-token":myXRSFToken
}
})
...
安全访问应用¶
开发者必须警惕任何不受信任或未经授权的用户访问您的应用。MindSphere使用角色,范围和令牌为每个注册的应用程序提供安全概念。有关此内容的更多信息,请参见角色和范围部分。
示例¶
在本例中,我们利用 expressjs 和一个定制中间件保护应用程序(每个端点),拦截每个请求并验证请求令牌是否包含应用的特定范围。
var jwt = require('jsonwebtoken');
var path = require('path');
var includes = require('lodash/includes')
const express = require('express')
const app = express()
// Middleware for checking the scopes in the user token
app.use('/', function (req, res, next) {
const authorizationHeader = authHeader = req.get("authorization");
var scopes = [];
if (authorizationHeader != null) {
token = jwt.decode(authorizationHeader.replace("bearer ", ""), { complete:true, json:true })
scopes = token.payload.scope;
}
console.log("scopes: ", scopes); // output all scopes
if (includes(scopes, `${config.mdsp.appname}.${config.mdsp.scope}`)) {
console.log("request with valid application token")
next();
} else {
console.log("unauthorized request");
res.status(403).send('no access!');
}
});
...
令牌日志
生产代码中不输出任何类似令牌的机密日志!
信息
切记,本示例仅作说明之用,不用于生产用途。 视应用的复杂程度而定,您可能需要使用不同的框架和多个范围来保护端点。
令牌验证¶
我们还建议对应用所使用的所有令牌进行验证。RFC 7519 对 JWT 访问令牌的验证进行了定义。
验证建议¶
以下章节给出了验证令牌的更多提示。
提示
有一些库可用于验证 JWTs, 例如 https://jwt.io.
有效载荷验证¶
用以下载荷声明验证访问令牌:
声明 | 条件 |
---|---|
iss | 必须是受信任的签发方名称。默认情况下,应用只能信任其应用提供者的签发方(即,只信任由应用提供者的 Provider IAM 系统所签发的访问令牌)。在开发租户和操作租户上,应用的签发方遵循以下方案:https://{tenantName}.piam.{region}.{mindsphere-domain}/oauth/ 。 |
exp | 应在当前日期/时间之后。开发人员可以留出几分钟的余地,以允许时钟偏移。 |
iat | 应早于或等于当前日期/时间。开发人员可以留出几分钟的余地来允许时钟偏移。 MindSphere发行的令牌中不包含 nbf 声明。 |
scope | 应与web应用程序或web API所期望的值匹配, 例如 api1.do . |
aud | 如果受众是在范围值中编码的,则此步骤是可选的。 应与web应用程序或web API所期望的值匹配,例如 api1 . |
签名验证¶
- 通过检查
alg
声明的值来验证访问令牌是使用受信任的预期算法进行签发。 MindSphere不使用alg
=none
签发JWT。 目前, MindSphere用RS256
签发所有令牌。 - 验证令牌头中
kid
声明使用 token issuer中的有效公钥。 -
验证公钥签名使用引用的算法和公钥。
用于验证签名的公钥
MindSphere操作员或开发人员租户颁发的令牌签名验证公钥位于:
https://{tenant_name}.piam.{region}.{mindsphere_domain}/token_keys
。 确保使用TLS从 受信任源 下载公钥。 更多信息请参考 OAuth Authorization Server documentation.用于创建和验证令牌签名的密钥对在MindSphere中定期更新。使用这些密钥的组件应该定期检查更新。