?
本文檔使用 php中文網手冊 發(fā)布
憑證 API 提供了一種從用戶那里收集用戶名和密碼憑證的抽象方式(即使更廣泛的世界中的憑證可以采用多種形式,本文檔中的“憑證”一詞總是指用戶名和密碼對)。
本文檔描述了兩個接口:憑證子系統(tǒng)提供給 Git 其余部分的 C API ,以及 Git 用來與系統(tǒng)特定的“憑證助手”通信的協議。如果您正在編寫想要查看或提示輸入憑據的 Git 代碼,請參閱下面的 “C API” 部分。如果您想編寫自己的幫手,請參閱下面的“憑證助手”部分。
+-----------------------+| Git code (C) |--- to server requiring --->| | authentication|.......................|| C credential API |--- prompt ---> User+-----------------------+ ^ | | pipe | | v+-----------------------+| Git credential helper |+-----------------------+
Git 代碼(通常是遠程幫助程序)將調用 C API 來獲取憑證數據,如登錄名/密碼對( credential_fill )。API 本身會調用一個遠程助手(例如 “git credential-cache” 或 “git credential-store” ),它可以從商店中檢索憑證數據。如果憑證幫助程序找不到信息,C API 將提示用戶。然后,API 的調用者負責聯系服務器,并進行實際的身份驗證。
憑證 C API 旨在由需要獲取或存儲憑證的 Git 代碼調用。它以代表單個憑證的對象為中心,并提供三種基本操作:填充(通過調用助手和/或提示用戶獲取憑證),批準(將憑證標記為已成功使用,以便將其存儲以供以后使用),并拒絕(將憑證標記為不成功,以便可以從任何持久性存儲中將其刪除)。
struct credential
該結構表示一個用戶名/密碼組合以及任何關聯的上下文。所有字符串字段應該是堆分配的(如果它們不知道或不適用,則為 NULL )。各個上下文字段的含義與幫助程序協議中的對應字段相同; 請參閱下面的部分,了解每個字段的說明。
該helpers
結構的成員是一個string_list
助手。每個字符串都指定一個外部幫助程序,它將按順序運行以獲取或存儲憑證。請參閱下面的憑證助手部分。在查詢幫助器之前,該列表由API函數根據相應的配置變量填充,因此通常根本不需要調用者修改幫助器字段。
這個結構應該始終用CREDENTIAL_INIT
或credential_init
來初始化。
credential_init
初始化憑證結構,將所有字段設置為空。
credential_clear
釋放與憑證結構關聯的任何資源,并將其返回到原始初始化狀態(tài)。
credential_fill
指示憑證子系統(tǒng)通過首先咨詢助手填充傳遞的憑證結構的用戶名和密碼字段,然后詢問用戶。此函數返回后,憑證的用戶名和密碼字段將保證為非 NULL。如果發(fā)生錯誤,該函數將死()。
credential_reject
通知憑證子系統(tǒng)所提供的憑證已被拒絕。這將導致憑證子系統(tǒng)通知拒絕的任何助手(例如,允許他們清除存儲中的無效憑證)。它還將釋放()用戶名和密碼字段的憑證并將它們設置為 NULL(準備另一次呼叫的憑證credential_fill
)。來自助手的任何錯誤都會被忽略。
credential_approve
通知憑證子系統(tǒng)所提供的憑證已成功用于身份驗證。這將導致憑證子系統(tǒng)通知任何助手的批準,以便他們可以存儲結果再次使用。來自助手的任何錯誤都會被忽略。
credential_from_url
將 URL 解析為已破解的憑證字段。
下面的示例顯示了憑證 API 的功能如何用于登錄到遠程主機上虛構的 “foo” 服務:
int foo_login(struct foo_connection *f){ int status; /* * Create a credential with some context; we don't yet know the * username or password. */ struct credential c = CREDENTIAL_INIT; c.protocol = xstrdup("foo"); c.host = xstrdup(f->hostname); /* * Fill in the username and password fields by contacting * helpers and/or asking the user. The function will die if it * fails. */ credential_fill(&c); /* * Otherwise, we have a username and password. Try to use it. */ status = send_foo_login(f, c.username, c.password); switch (status) { case FOO_OK: /* It worked. Store the credential for later use. */ credential_accept(&c); break; case FOO_BAD_LOGIN: /* Erase the credential from storage so we don't try it * again. */ credential_reject(&c); break; default: /* * Some other error occurred. We don't know if the * credential is good or bad, so report nothing to the * credential subsystem. */ } /* Free any associated resources. */ credential_clear(&c); return status;}
憑證助手是由 Git 執(zhí)行的程序,用于從長期存儲中獲取或保存憑據(其中“長期”比單個 Git 流程更長;例如,憑證可以存儲在內存中幾分鐘,或者無限期地在磁盤上)。
每個助手都由配置變量中的單個字符串credential.helper
(以及其他字符串,請參閱 git-config [1] )指定。該字符串通過 Git 轉換為使用這些規(guī)則執(zhí)行的命令:
1. 如果輔助字符串以“!”開頭,則它被認為是一個 shell 代碼片段,并且“!”之后的所有內容都成為命令。
2. 否則,如果輔助字符串以絕對路徑開始,則逐字幫助字符串變成命令。
3. 否則,字符串“git credential-”被預先添加到助手字符串中,結果變成命令。
然后生成的命令會附加一個“操作”參數(詳情參見下文),結果由 shell 執(zhí)行。
以下是一些示例說明:
# run "git credential-foo"foo # same as above, but pass an argument to the helper foo --bar=baz # the arguments are parsed by the shell, so use shell # quoting if necessary foo --bar="whitespace arg"# you can also use an absolute path, which will not use the git wrapper/path/to/my/helper --with-arguments # or you can specify your own shell snippet!f() { echo "password=`cat $HOME/.secret`"; }; f
一般來說,上面的規(guī)則(3)對用戶來說是最簡單的。憑證助手的作者應該努力通過命名他們的程序 “git-credential- $ NAME” 來幫助他們的用戶,并且在安裝時將其放在 $ PATH 或 $ GIT_EXEC_PATH 中,這將允許用戶使用它和git config credential.helper $NAME
。
當執(zhí)行幫助程序時,它的命令行中會附加一個“操作”參數,該參數是以下之一:
get
返回匹配的憑證(如果存在)。
store
存儲憑證(如果適用于助手)。
erase
從助手的存儲中刪除匹配的憑據(如果有)。
憑證的詳細信息將在助手的 stdin 流中提供。確切的格式與git credential
管道命令的輸入/輸出格式相同(INPUT/OUTPUT FORMAT
有關詳細規(guī)范,請參閱 git-credential [1] 中的部分)。
對于get
操作,幫助者應該以相同的格式在 stdout 上產生一個屬性列表。輔助者可以自由地產生一個子集,或者如果它沒有任何用處可以提供的話,甚至根本沒有值。任何提供的屬性都會覆蓋 Git 已知的那些屬性。如果助手輸出quit
值為true
或屬性1
,則不會再咨詢幫助者,也不會提示用戶(如果沒有提供憑證,則操作將失?。?。
對于 store
或erase
操作,幫助器的輸出將被忽略。如果它未能執(zhí)行請求的操作,它可能會向 stderr 投訴以通知用戶。如果它不支持請求的操作(例如只讀存儲),它應該默默地忽略該請求。
如果助手收到任何其他操作,它應該默默地忽略該請求。這為未來的操作留下了余地(較舊的幫助者將忽略新的請求)。