原文鏈接
<meta name="ProgId" content="Word.Document"> <meta name="Generator" content="Microsoft Word 11"> <meta name="Originator" content="Microsoft Word 11"> <link rel="File-List" href="file:///C:%5CDOCUME%7E1%5CADMINI%7E1%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C03%5Cclip_filelist.xml"> <link rel="Edit-Time-Data" href="file:///C:%5CDOCUME%7E1%5CADMINI%7E1%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C03%5Cclip_editdata.mso"> <!--[if !mso]> <style> v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VML);} .shape {behavior:url(#default#VML);} </style> <![endif]--><!--[if gte mso 9]><xml> <w:worddocument> <w:view>Normal</w:view> <w:zoom>0</w:zoom> <w:punctuationkerning/> <w:drawinggridverticalspacing>7.8 磅</w:drawinggridverticalspacing> <w:displayhorizontaldrawinggridevery>0</w:displayhorizontaldrawinggridevery> <w:displayverticaldrawinggridevery>2</w:displayverticaldrawinggridevery> <w:validateagainstschemas/> <w:saveifxmlinvalid>false</w:saveifxmlinvalid> <w:ignoremixedcontent>false</w:ignoremixedcontent> <w:alwaysshowplaceholdertext>false</w:alwaysshowplaceholdertext> <w:compatibility> <w:spaceforul/> <w:balancesinglebytedoublebytewidth/> <w:donotleavebackslashalone/> <w:ultrailspace/> <w:donotexpandshiftreturn/> <w:adjustlineheightintable/> <w:breakwrappedtables/> <w:snaptogridincell/> <w:wraptextwithpunct/> <w:useasianbreakrules/> <w:dontgrowautofit/> <w:usefelayout/> </w:compatibility> <w:browserlevel>MicrosoftInternetExplorer4</w:browserlevel> </w:worddocument> </xml><![endif]--><!--[if gte mso 9]><xml> <w:latentstyles deflockedstate="false" latentstylecount="156"> </w:latentstyles> </xml><![endif]--><style> <!-- /* Font Definitions */ @font-face {font-family:宋體; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:SimSun; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:"\@宋體"; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; mso-pagination:none; font-size:10.5pt; mso-bidi-font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:宋體; mso-font-kerning:1.0pt;} h4 {mso-margin-top-alt:auto; margin-right:0cm; mso-margin-bottom-alt:auto; margin-left:0cm; mso-pagination:widow-orphan; mso-outline-level:4; font-size:12.0pt; font-family:宋體; mso-bidi-font-family:宋體;} a:link, span.MsoHyperlink {color:blue; text-decoration:underline; text-underline:single;} a:visited, span.MsoHyperlinkFollowed {color:purple; text-decoration:underline; text-underline:single;} pre {margin:0cm; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:12.0pt; font-family:宋體; mso-bidi-font-family:宋體;} /* Page Definitions */ @page {mso-page-border-surround-header:no; mso-page-border-surround-footer:no;} @page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;} div.Section1 {page:Section1;} --> </style> <!--[if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable {mso-style-name:普通表格; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman"; mso-ansi-language:#0400; mso-fareast-language:#0400; mso-bidi-language:#0400;} </style> <![endif]-->
Windows Credential Management with the .net Framework 2.0
Kenny kerr
January 2006
Applies to:
Microsoft .NET Framework 2.0
NET Framework Security
Windows XP
概敘:這篇文章主要是介紹
Credential Management API
怎樣處理界面和用戶的憑證集合。同時也提供了一個能夠做一些簡單憑證管理的類庫,可以被
c#
和
vb.net
調用。
下載相關的例程:
KerrCredentialsSample.exe
內容
介紹
請求憑證
托管代碼的請求憑證
一個工具:請求憑證生成器
SecureString
基礎
憑證集合
在托管代碼中使用憑證集合
工具:憑證集合管理器
結論
?
?
介紹
管理用戶憑證是一件非常困難的事情。理想上你的
windows
域憑證應該有足夠的權限來訪問你可能需要的資源。但是有這么簡單嗎?你可能不可避免的要去處理不同的安全權限,包括
windows
域,
Microsoft Passport
和應用程序指定的驗證策略。好像那些還不夠挑戰,憑證可能來自不同的
form
,包括
smart cards, certificates
和密碼。
?
自從
2001
年
windows xp
發布,
windows
包含了
credential management api
去管理用戶憑證。這些
api
的設計是為了簡化內部程序用戶憑證管理,也為你自己的相關憑證管理提供了一致的安全的方法。她也可以被用來請求不需要被持久化的憑證,或者持久化你的應用程序的憑證,比如用數據保護
api
(
Data Protection API
)
.
?
在這篇文章我會介紹
windows credential management api
,
包括界面處理,憑證集合管理。介紹這些
api
的一個挑戰是依賴你的背景知識和你怎么去用她,這些是一個
c-style
的
api
,適用于
visual c++
或者任何一款支持
windows
的編譯器。因為流行
.net
框架的原因,一個理想的解決方案還應該包括
.net
框架的支持托管代碼的集合。所以也提供了一個功
.net
框架調用的類庫。
?
最后要說明的是:
當我解釋
windows credential management
用到的不同的函數,結構,也包括列在表格中的相關的選項,標志和屬性。雖然這些選項我的解釋很多都是依賴與
sdk
和
msndn
類庫,但是我不止是簡單的從文檔中
copy
說明,我是盡力想你說明她的一些你可能不能完全掌握的細節。這些都是基于我寫
credential management
經驗的積累。
?
請求憑證
如果你所需要得是你得域憑證,那么你不需要請求憑證。因為在你登陸會話時已經被驗證,你可以訪問你可能能訪問的所有資源。明顯的這是一個不現實的例子。所以你需要請求用戶的憑證。在過去,不用的應用程序創建不用的用戶界面來請求用戶的憑證,但是在
windows xp
上,應用程序可以依靠內建的,簡單的,安全的用戶界面給用戶輸入。
Windows
提供了
CredUIPromptForCredentials
函數顯示一個可以配置的窗體去接收用戶的憑證信息。
DWORD WINAPI CredUIPromptForCredentialsW(PCREDUI_INFOW info,
????????????????????????????????????????
PCWSTR targetName,
????????????????????????????????????????
PCtxtHandle reserved,
????????????????????????????????????????
DWORD errorCode,
????????????????????????????????????????
PWSTR userName,
?????????????????
???????????????????????
ULONG userNameBufferSize,
????????????????????????????????????????
PWSTR password,
??????????????????????????????????????????
ULONG passwordBufferSize,
????????????????????????????????????????
PBOOL saveChecked,
DWORD flags);
因為這篇文章不是關于用
c
或者非托管的
c++
來管理用戶憑證,所以我不對這個函數做過多細節的描敘。
?
第一個參數只向一個
CREDUI_INFO
結構的指針,它允許你指定它的父窗體和默認的圖標,標題,信息。
?
targetName
參數用來讀取和寫入憑證時的唯一定義,也被用來作為標題和信息的一部分,如果
CREDUI_INFO
沒有被重寫的話,晚些在我們討論
persisting
憑證的時候你會對她認識的更深刻。
Errorcode
參數允許窗體提供相應的錯誤代碼,但是
sdk
沒有提供相應的鏈接,所以這個參數幾乎沒什么用。
username
和
userNameBufferSize
參數用來指定初始化時的用戶名。相應的
password
和
passwordBufferSize
用來指定初始化的用戶密碼。這些使得用
c
和非托管的
c++
編程相當困難,你必須非常小心的處理這些字符串,像你在下一章看到的,托管代碼可以非常簡單的寫出非常優秀的代碼。
?
這個窗體可以顯示一個
check box
提供給用戶來選擇是否保存憑證。
saveChecked
參數就是用來初始化這個
check box
的狀態用的。這個
check box
也可以在用戶關閉窗體的時候來判斷用戶的喜好。注意的是這個參數被忽略,當憑證不是
generic
憑證的時候。
?
最好,
falgs
參數允許你指定一個聯合的標識。這里的問題是錯誤的混合不同的標識也會導致程序的錯誤。
?
相比探索這個函數的更多細節,我將會提供一些為簡單任務的解決方案給你,用托管代碼寫的。在那之前,我們先來看一看一個用
C++
寫的例子。這個例子調用
CredUIPromptForCredentials
?
CREDUI_INFO info = { sizeof (CREDUI_INFO) };
info.hwndParent = GetSafeHwnd();
info.pszCaptionText = L"Title";
info.pszMessageText = L"Message";
CBitmap bitmap;
VERIFY(bitmap.LoadBitmap(IDB_PROMPT_BITMAP));
info.hbmBanner = bitmap;
CString target;
const DWORD errorCode = 0;
wchar_t userName[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
wcscpy_s(userName,
????????
_countof(userName),
????????
L"initial user name");
wchar_t password[CREDUI_MAX_PASSWORD_LENGTH + 1] = { 0 };
BOOL saveChecked = false;
Const DWORD flags = CREDUI_FLAGS_DO_NOT_PERSIST |
????????????????????
CREDUI_FLAGS_SHOW_SAVE_CHECK_BOX ;
DWORD result = ::CredUIPromptForCredentials(&info,
???????????????????????????????????????????
target,
???????????????????????????????????????????
0, // reserved
???????????????????
????????????????????????
errorCode,
???????????????????????????????????????????
userName,
???????????????????????????????????????????
_countof(userName)
???????????????????????????????????????????
password,
???????????????????????????????????????????
_countof(password)
???????????????????????????????????????????
&saveChecked,
???????????????????????????????????????????
flags);
switch (result)
{
???
case NO_ERROR:
???
{
???????
// User chose OK...
???????
break;
???
}
???
case ERROR_CANCELLED:
???
{
??????
?
// User chose Cancel...
???????
break;
???
}
???
default:
???
{
???????
// Handle all other errors...
???
}
}
::SecureZeroMemory(password,
??????????????????
sizeof (password));
這段代碼的結果是顯示一下的窗體:
<!--[if gte vml 1]><v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"> <v:stroke joinstyle="miter"/> <v:formulas> <v:f eqn="if lineDrawn pixelLineWidth 0"/> <v:f eqn="sum @0 1 0"/> <v:f eqn="sum 0 0 @1"/> <v:f eqn="prod @2 1 2"/> <v:f eqn="prod @3 21600 pixelWidth"/> <v:f eqn="prod @3 21600 pixelHeight"/> <v:f eqn="sum @0 0 1"/> <v:f eqn="prod @6 1 2"/> <v:f eqn="prod @7 21600 pixelWidth"/> <v:f eqn="sum @8 21600 0"/> <v:f eqn="prod @7 21600 pixelHeight"/> <v:f eqn="sum @10 21600 0"/> </v:formulas> <v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/> <o:lock v:ext="edit" aspectratio="t"/> </v:shapetype><v:shape id="_x0000_i1025" type="#_x0000_t75" style="'width:246pt; height:218.25pt'"> <v:imagedata src="file:///C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\msohtml1\03\clip_image001.png" o:title=""/> </v:shape><![endif]--><!--[if !vml]-->
<!--[endif]-->
正像你所看到的,有一大段代碼是為了調用這個函數不會出錯,首先,你要熟悉結構
CREDUI_INFO
去控制這個窗體的不同元素。接下來,你要為接收的用戶名合密碼準備緩沖區。和顯示初始值。
CREDUI_MAX_USERNAME_LENGTH
常量表示用戶名的最大長度。相同的
CREDUI_MAX_PASSWORD_LENGTH
表示密碼的可能最大長度。在用戶名和密碼長度后面加
1
是為了加上介紹字符串
NULL,
調用
wcscpy_s
函數是為了顯示用戶名和密碼的初始值。最后,我指定了兩個標識,意思是,我不想
persist
這個憑證但是我想讓保存密碼的
check box
顯示。
saveChecked
將會包括用戶的選項。
顯然在這里你很容易出錯。
?
請求憑證,用托管代碼
因為
CredUIPromptForCredentials
[C++]
ref class MainWindow : Windows::Forms::Form
{
public:
?
???
void Prompt()
???
{
???????
PromptForCredentials dialog;
?
???????
dialog.Title = "Title";
???????
dialog.Message = "Message";
???????
dialog.Banner = Images::Banner;
???????
dialog.UserName = "initial user name";
?
???????
dialog.DoNotPersist = true;
???????
dialog.ShowSaveCheckBox = true;
?
???????
if (Windows::Forms::DialogResult::OK == dialog.ShowDialog(this))
???????
{
???????????
// Use credentials wisely...
???????
}
???
}
};
[C#]
class MainWindow : Form
{
???
public void Prompt()
???
{
???????
using (PromptForCredentials dialog = new PromptForCredentials())
???????
{
???????????
dialog.Title = "Title";
???????????
dialog.Message = "Message";
?
??????????
dialog.Banner = Images.Banner;
???????????
dialog.UserName = "initial user name";
?
???????????
dialog.DoNotPersist = true;
???????????
dialog.ShowSaveCheckBox = true;
?
???????????
if (DialogResult.OK == dialog.ShowDialog(this))
???????????
{
???
????????????
// Use credentials wisely...
???????????
}
???????
}
???
}
}
Windows Credential Management with the .net Framework 2.0