IOM、OAuth 与 OData
Aras Innovator 对外提供两条常用集成路径:.NET 应用可以使用 IOM(Innovator Object Model),HTTP 客户端可以使用 RESTful API / OData。两者最终都受服务器端权限和业务逻辑约束,但 SDK 分发、认证方式和端点会随 Release 演进。
核验基线
- IOM 对象模型与 CRUD 示例以 Aras Innovator 35 Programmer's Guide 为基线。
- OAuth 与 OData 以 Aras Innovator 35 RESTful API 为基线。
- Release 12 及以下的 token 认证与 14+ 不同;不要把一套登录示例复制到所有版本。
- 从 Release 35 开始,Aras IOM SDK 作为独立包交付,不再随 Innovator CD Image 捆绑。
选择 IOM 还是 OData
| 场景 | 建议 | 原因 |
|---|---|---|
| .NET 服务、迁移工具、复杂 AML | IOM SDK | 与 Item/AML 模型直接对应 |
| 浏览器之外的通用 HTTP 集成 | RESTful API / OData | 标准 HTTP 与 JSON |
| 交互式用户登录 | OAuth Authorization Code + PKCE | 不把用户密码交给客户端应用 |
| 后台服务 | 经管理员注册并批准的服务客户端 | 凭据可治理、可轮换 |
| Aras 网页内的简单操作 | 当前客户端提供的 IOM 入口 | 不要重复建立外部登录会话 |
IOM 的核心对象
IomFactory / connection
│
▼
Innovator
│
▼
Item ──► AML request / response- Connection 负责发现、认证、会话与 HTTP 传输。
Innovator是创建 Item 和调用服务器的入口。Item同时表示请求、单条结果、结果集合或错误。
服务器 Method 已经处于登录会话中,应直接取得当前 Innovator:
Innovator inn = this.getInnovator();客户端 Classic Method 常由当前 aras 上下文取得 IOM 实例,但具体属性名按 Release 和调用位置核验。不要在页面脚本中硬编码另一组管理员凭据。
外部 .NET 连接
获取匹配的 SDK
使用与目标 Innovator Release 兼容的 Aras IOM SDK。不要随意从服务器 bin 目录复制一个 DLL,再假设它适用于任意 .NET Runtime 或服务器版本。
从 Release 35 开始,官方 Programmer's Guide 指向独立的 Aras IOM SDK 及其自带文档。连接代码应以该 SDK 版本的示例为准。
认证原则
不要自己设计密码协议
旧文档常把 MD5(password) 写成所有 IOM 与 REST 连接的强制要求,这是错误的绝对化描述。官方 IOM 支持的连接重载和 OAuth provider 会随 SDK 版本变化;应使用 SDK 的 DiscoveryDocumentProvider / token provider 或该版本明确支持的连接工厂。不要把 MD5 当作现代密码保护方案,也不要把明文、哈希或 client secret 写进源码。
以官方 R27 .NET IOM 文档为例,CreateHttpServerConnection 的密码参数允许传入明文或已加密值,明文会由 SDK 内部处理;这已经足以否定“必须由业务代码手写 MD5”。R35+ 项目则应优先采用同版本 SDK 的 discovery/token provider 模型。
下面是外部程序应遵循的结构,而不是可以跨版本复制的构造函数签名:
// 伪代码:具体 provider 与 factory 签名以所安装的 IOM SDK 为准。
var discovery = LoadDiscoveryDocument(serverBaseUrl);
var tokenProvider = CreateApprovedTokenProvider(discovery, clientRegistration);
var connection = CreateConnection(serverBaseUrl, database, tokenProvider);
try
{
Item login = connection.Login();
if (login.isError())
{
throw new InvalidOperationException(login.getErrorDetail());
}
Innovator inn = CreateInnovator(connection);
// 执行业务操作。
}
finally
{
connection.Logout();
}之所以保留为伪代码,是为了避免再制造一份与 SDK 重载不匹配的教程。真正项目应把对应版本 IOM SDK Programmer's Guide 中的连接例复制进集成测试,并由密钥管理系统注入配置。
IOM CRUD
查询
Item query = inn.newItem("Part", "get");
query.setAttribute("select", "id,item_number,name");
query.setProperty("item_number", "P-10023");
Item result = query.apply();
if (result.isError())
{
throw new InvalidOperationException(result.getErrorDetail());
}
for (int i = 0; i < result.getItemCount(); i++)
{
Item part = result.getItemByIndex(i);
Console.WriteLine(part.getProperty("item_number", ""));
}创建
Item part = inn.newItem("Part", "add");
part.setProperty("item_number", "P-2026-999");
part.setProperty("name", "Integration Sample");
Item created = part.apply();
if (created.isError())
{
throw new InvalidOperationException(created.getErrorDetail());
}
string newId = created.getID();编辑
Item edit = inn.newItem("Part", "edit");
edit.setID(partId);
edit.setProperty("name", newName);
Item updated = edit.apply();
if (updated.isError())
{
throw new InvalidOperationException(updated.getErrorDetail());
}编辑能否成功取决于 Permission、锁定、生命周期状态、版本规则和服务器事件。不要用 applySQL() 绕开这些机制。
OAuth 2.0(14+)
Aras Innovator 35 RESTful API 指南给出的交互式示例使用 Authorization Code with PKCE:
Authorization endpoint:
https://<host>/<web-alias>/oauthserver/connect/authorize
Token endpoint:
https://<host>/<web-alias>/oauthserver/connect/token
官方示例中的 callback(不是通用值):
https://<host>/<web-alias>/Client/OAuth/PopupCallbackAuthorization 与 token endpoint 应由当前部署的 discovery document 确定。PopupCallback 只是官方示例客户端使用的 redirect URI;自建客户端必须使用管理员在 OAuth Registry 中为该 client_id 注册的 redirect URI,不能照抄。上面的 <web-alias> 也不能省略,端点不能换回旧示例中的 /Server/oauth.ashx/token。
为什么不提供 password grant 粘贴代码
- 交互式应用应使用 Authorization Code + PKCE。
- 后台客户端需要管理员批准的注册、作用范围和 secret/certificate 管理。
- 不同 Release、IOM SDK 和部署策略支持的 grant 不完全相同。
- 在文档中展示真实密码、MD5 密码或 client secret 都是不安全的习惯。
Release 12 及以下
官方 R35 RESTful API 明确指出,Release 12 及以下需要不同的认证步骤。旧系统应查该版本文档并安排升级,不要把 14+ OAuth 端点硬套进去。
R12 官方流程先访问 /<alias>/Server/OAuthServerDiscovery.aspx,再读取发现结果所指向的 OpenID configuration,并使用其中的 token_endpoint。这仍然是 discovery 流程,不应改成硬编码旧 token URL。
OData 查询
取得 Bearer token 后,通过 OData 访问 Item。下面请求使用占位 ID:
GET https://<host>/<web-alias>/server/odata/Part('PART_ID')?$select=id,item_number,name HTTP/1.1
Authorization: Bearer <access-token>
Accept: application/json筛选、选择与展开
GET https://<host>/<web-alias>/server/odata/Part?$select=id,item_number,name&$filter=state eq 'Released' HTTP/1.1
Authorization: Bearer <access-token>
Accept: application/json展开创建者:
GET https://<host>/<web-alias>/server/odata/Part?$select=id,item_number&$expand=created_by_id HTTP/1.1
Authorization: Bearer <access-token>
Accept: application/json展开关系时,ItemType / RelationshipType 名中的空格需要按 URL 规则正确编码。不要直接把用户输入拼进 $filter。
更新
官方 R35 文档使用 PATCH 更新指定 Item:
PATCH https://<host>/<web-alias>/server/odata/Part('PART_ID') HTTP/1.1
Authorization: Bearer <access-token>
Content-Type: application/json
Accept: application/json
{
"name": "Updated by integration"
}一次 update action 只修改一个 Item。批处理、重试与幂等性应由集成服务显式设计。
下载 File
对 File 关系的 related_id/$value 发起请求时,OData 服务会根据当前用户的 Vault priority 构造文件访问并重定向到 Vault。客户端必须安全处理重定向和授权头,不应拿普通静态 <a> 下载替代 Vault 权限流程。
错误、分页与可观察性
IOM
- 每次
apply()后先检查isError()。 - 再按业务约束检查
getItemCount()。 - 日志记录 correlation、操作名和安全裁剪后的错误,不记录密码或 token。
HTTP
- 区分
401(认证)、403(授权)、404(资源/路由)和并发冲突。 - 仅对可安全重试的请求重试,并采用退避。
- 读取分页链接或按目标 API 的分页规则请求,不能假设单次返回全集。
- token 缓存要考虑过期与时钟偏差;不要把 token 输出到普通日志。
集成验收清单
- SDK、服务器 Release 和目标 .NET Runtime 有明确兼容证据。
- endpoint 来自 discovery 或当前 Release 官方文档。
- 凭据由 secret store 注入,可轮换,不入 Git。
- 使用最小权限专用 Identity,而不是
admin/root。 - 普通查询显式使用
$select或 AMLselect。 - 写操作具备幂等键、超时、重试和审计。
- 测试覆盖 401、403、0 条、多条、超时和 token 过期。
- 没有直接 SQL 修改业务数据。
版本差异
| Release | 重点 |
|---|---|
| 11 / 12 | 旧认证和旧客户端资料只能作为历史参考 |
| 14+ | REST token authentication 使用 OAuth 2.0 路线 |
| 35 | IOM SDK 改为独立交付;查 SDK 自带 Programmer's Guide |
| 39 | 服务器运行时升级为 .NET 10;集成 SDK 仍需按兼容矩阵选择 |
