認證名稱自動遞增似乎對自訂認證是全域的,但對某些內建認證(OpenAI)則是按個人計算

{“content”:“我在 n8n 中看到了不一致的認證命名行為,想確認這是否是預期的。\n\n### 我觀察到的情況\n\n* 對於我的自訂認證類型 (myApi),新認證在整個執行個體中會自動全域命名:\n\n * 使用者 A 建立個人認證:MyApi AccountMyApi Account 2\n\n * 使用者 B(看不到使用者 A 的個人認證)建立認證時,會得到:MyApi Account 3\n\n* 但例如OpenAI 認證,計數器似乎是個人/專案範圍的(它不會以相同的方式從同一執行個體中其他使用者的認證繼續)。\n\n### 為什麼這令人困惑\n\n認證可見性是個人/專案型的,但我的自訂類型產生的名稱後綴似乎使用全域計數器。這使得命名看起來像在使用者之間「洩漏」,即使認證並未共享。\n\n### 問題\n\n* 內建(例如 OpenAI)和自訂認證類型之間的這種差異是預期的嗎?\n\n* n8n 中是否存在多個認證建立/名稱產生流程來解釋這種情況?\n\n* 自訂認證類型是否有任何方式可以使用每個使用者/每個專案的名稱產生,而不是全域後綴?\n\n\"n8n-workflow\": \"^1.120.13\"”,“target_locale”:“zh_TW”}

歡迎來到 n8n 社區 @Jankaz
你是否驗證過 openai 認證是否由與你的自訂認證相同的流程建立(個人專案 vs 共享專案 vs 所有者全域專案)?
我認為你的問題在於正在使用的內部建立/命名路徑。你能分享一個簡單的重現案例,比較自訂認證 vs OpenAI 認證,包括專案、使用者角色、產生的名稱和使用者之間的編號行為嗎?

我檢查了網路中的請求,兩者都使用https://n8n.stg.olx.org/rest/credentials,具有相同的酬載結構。兩者都使用相同的projectId。唯一的區別是openai的酬載有額外的欄位uiContext: "credentials_list",但我認為這不是問題所在

MyApi.credentials.ts

export class MyApi implements ICredentialType {
  name = "myApi";

  displayName = "My API";

  properties: INodeProperties[] = [
    {
      displayName: "平台基礎 URL",
      name: "baseUrl",
      type: "string",
      default: "http://myapi.com",
      placeholder: "http://myapi.com",
      required: true,
      hint: "點擊 `Save` 進行驗證。",
      description: "",
    },
    {
      displayName: "密鑰",
      name: "adminToken",
      type: "hidden",
      typeOptions: {
        password: true,
      },
      default: "",
      description:
        "通過 n8n 認證覆蓋進行填充。",
    },
  ];

  test: ICredentialTestRequest = {
    request: {
      method: "GET",
      baseURL: "={{$credentials.baseUrl}}",
      url: "/health",
    },
  };
}

import type {
  ICredentialDataDecryptedObject,
  ICredentialTestRequest,
  ICredentialType,
  IHttpRequestOptions,
  INodeProperties,
} from 'n8n-workflow';

export class OpenAiApi implements ICredentialType {
  name = 'openAiApi';

  displayName = 'OpenAI';

  documentationUrl = 'openai';

  properties: INodeProperties[] = [
   {
    displayName: 'API 密鑰',
    name: 'apiKey',
    type: 'string',
    typeOptions: { password: true },
    required: true,
    default: '',
   },
   {
    displayName: '組織 ID(選填)',
    name: 'organizationId',
    type: 'string',
    default: '',
    hint: '僅在您屬於多個組織時才需要',
    description:
     "對於屬於多個組織的使用者,您可以設定 API 請求使用哪個組織。來自這些 API 請求的使用量將計入指定組織的訂閱配額。",
   },
   {
    displayName: '基礎 URL',
    name: 'url',
    type: 'string',
    default: 'https://api.openai.com/v1',
    description: '覆蓋 API 的預設基礎 URL',
   },
   {
    displayName: '新增自訂標頭',
    name: 'header',
    type: 'boolean',
    default: false,
   },
   {
    displayName: '標頭名稱',
    name: 'headerName',
    type: 'string',
    displayOptions: {
     show: {
      header: [true],
     },
    },
    default: '',
   },
   {
    displayName: '標頭值',
    name: 'headerValue',
    type: 'string',
    typeOptions: {
     password: true,
    },
    displayOptions: {
     show: {
      header: [true],
     },
    },
    default: '',
   },
  ];

  test: ICredentialTestRequest = {
   request: {
    baseURL: '={{$credentials?.url}}',
    url: '/models',
   },
  };

  async authenticate(
   credentials: ICredentialDataDecryptedObject,
   requestOptions: IHttpRequestOptions,
  ): Promise<IHttpRequestOptions> {
   requestOptions.headers ??= {};

   requestOptions.headers['Authorization'] = `Bearer ${credentials.apiKey}`;
   requestOptions.headers['OpenAI-Organization'] = credentials.organizationId;

   if (
    credentials.header &&
    typeof credentials.headerName === 'string' &&
    credentials.headerName &&
    typeof credentials.headerValue === 'string'
   ) {
    requestOptions.headers[credentials.headerName] = credentials.headerValue;
   }

   return requestOptions;
  }
}

@Jankaz
根據後端代碼,似乎 POST /rest/credentials 會保存 payload 中接收到的 name,所以我會在請求發送之前調查前端中名稱的生成。如果 OpenAI 和自訂認證到達相同的端點且具有相同的 projectId,但已經有不同的名稱,差異可能在於計算預設認證名稱的 UI 流程中,而不是後端的 save() 中。

感謝 - 同意 POST `/rest/credential` 只是儲存提供的名稱。
在網路追蹤中,OpenAI 和自訂認證也都會在 POST 之前呼叫 GET /rest/credentials/new?name=`... ``。 所以命名似乎是由 (a) 前端基本名稱 + (b) 後端在/credentials/new 中的唯一名稱生成決定。 這表示差異來自於每個前綴的現有名稱匹配(OpenAI account%對比GAIP account%),而不是來自 save()uiContext`。

所以..重新命名憑證有什麼困難嗎? :slight_smile:

我使用 n8n 大約 4 年了,我發現保留預設名稱會導致後續更新憑證或確定各個憑證用途時出現問題

沒有難度,但很容易令人困惑

這是正常的 @Jankaz,當你找到自己理解這個問題的方式後,就會變得更容易。不是可配置的東西,它們在視覺上本身就是不同的。

我沒有找到任何參數來改變自動生成名稱的邏輯

按使用者/專案的分隔存在於權限和認證的可見性級別,通過 RBAC/Projects,但這並不意味著自動名稱計數器也是按專案範圍劃分的。RBAC 文檔談論的是按專案存取工作流程和認證,而不是命名演算法。

如同線程中的建議,解決方法是在名稱中手動包含專案/使用者來命名認證。