Chinaunix首页 | 论坛 | 博客
  • 博客访问: 645612
  • 博文数量: 751
  • 博客积分: 5000
  • 博客等级: 大校
  • 技术积分: 4990
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-28 09:48
文章分类

全部博文(751)

文章存档

2011年(1)

2008年(750)

我的朋友

分类:

2008-10-28 10:06:35


  简介
  有时,应用程序要求有用户提供的凭据以便访问受保护的资源,如数据库或 FTP 网站。然而,获取并用户的 ID 和密码可能会给您的系统带来风险。如有可能,您根本不应该让用户提供凭据(例如,通过对数据库使用集成身份验证),但有时这无法避免。如果您确实要求用户提供凭据,并且您的应用程序将运行在 Microsoft??XP 或 Microsoft? Server 2003 上,则相应的操作系统会提供函数以使此任务变得容易一些。
  
  的用户名和密码
  Windows XP 和 Windows Server 2003 使用一种称为“存储的用户名和密码”的功能(参见图 1)将一组凭据与单个 Windows 用户帐户相关联,并使用数据保护 API (DPAPI) 来存储这些凭据。
  
 

  
图 1. Windows XP 中的 Credential Management 对话框

  
  如果您的应用程序运行在 Windows XP 或 Windows .NET 上,则可以使用凭据管理 API 函数来提示用户输入凭据。这些 API 可以为您提供一致的用户界面(参见图 2),并使您可以自动支持由操作系统来缓存这些凭据。
  
 

  
图 2. 标准 Windows XP 凭据对话框

  
  有关在应用程序中请求、存储和使用用户凭据所涉及问题的详细讨论,请参阅 Michael Howard 与 David LeBlanc 合著的 Writing Secure Code 一书。建议您阅读该书,以获取更多信息。在本文中,我将只是向您说明如何在 Microsoft?Visual Basic?.NET 和 应用程序中使用凭据管理 API。
  
  在 .NET 中创建凭据 API 类
  声明 API 函数
  因为这些凭据管理函数是 Win32 API 调用,您将需要创建 extern () 或 Declare (Visual Basic .NET) 定义以便访问它们。除了这些函数本身以外,还需要使用一些常数和结构来访问它们。这些常数被组织为预定义的常数组,所以我已经选择在 .NET 代码中以枚举形式实现这些常数组,以使 API 调用更加易于使用。
  
  Private Declare Unicode _
  Function CredUIPromptForCredentials _
    Lib "credui" Alias "CredUIPromptForCredentialsW" _
      (ByRef creditUR As CREDUI_INFO, _
       ByVal targetName As String, _
       ByVal reserved1 As IntPtr, _
       ByVal iError As Integer, _
       ByVal userName As StringBuilder, _
       ByVal maxUserName As Integer, _
       ByVal password As StringBuilder, _
       ByVal maxPassword As Integer, _
       ByRef iSave As Integer, _
       ByVal flags As CREDUI_FLAGS) _
  As CredUIReturnCodes
  
  Private Declare Unicode _
  Function CredUIParseUserName _
    Lib "credui" Alias "CredUIParseUserNameW" _
      (ByVal userName As String, _
       ByVal user As StringBuilder, _
       ByVal userMaxChars As Integer, _
       ByVal domain As StringBuilder, _
       ByVal domainMaxChars As Integer) _
  As CredUIReturnCodes
  
  Private Declare Unicode _
  Function CredUIConfirmCredentials _
    Lib "credui" Alias "CredUIConfirmCredentialsW" _
      (ByVal targetName As String, _
       ByVal confirm As Boolean) _
  As CredUIReturnCodes
  
  Public Declare Auto _
  Function DeleteObject Lib "Gdi32" _
    (ByVal hObject As IntPtr) As Boolean
  
  注:我在代码中包括了 GDI32 库中的 DeleteObject API 调用,因为如果您决定将自己的位图传递给 CredUIPromptForCredentials API,则您将需要使用该调用。当我在下文中演示自定义位图的使用时,您将可以了解该 API 的使用方法。
  
  常数和结构声明
  对于许多 Win32 API 调用,您都需要一组支持常数(在本文中,我选择将其表示为枚举),并且还可能需要一个或两个结构声明。凭据 API 也遵循上述一般性规则,并且需要多种常数和一个结构。在我的 .NET 类中,我添加了一个枚举来表示 CredUIPromptForCredentials 的标志参数,添加了另外一个枚举来表示全部三个凭据 API 调用可能产生的返回代码集,并添加了一个 CREDUI_INFO 结构声明。
  
   Public Enum CREDUI_FLAGS
  INCORRECT_PASSWORD = &H1
  
  DO_NOT_PERSIST = &H2
  
  REQUEST_ADMINISTRATOR = &H4
  
  EXCLUDE_CERTIFICATES = &H8
  
  REQUIRE_CERTIFICATE = &H10
  
  SHOW_SAVE_CHECK_BOX = &H40
  
  ALWAYS_SHOW_UI = &H80
  
  REQUIRE_SMARTCARD = &H100
  
  PASSWORD_ONLY_OK = &H200
  
  VALIDATE_USERNAME = &H400
  
  COMPLETE_USERNAME = &H800
  
  PERSIST = &H1000
  
  SERVER_CREDENTIAL = &H4000
  
  EXPECT_CONFIRMATION = &H20000
  
  GENERIC_CREDENTIALS = &H40000
  
  USERNAME_TARGET_CREDENTIALS = &H80000
  
  KEEP_USERNAME = &H100000
  
  End Enum
  
  Public Enum CredUIReturnCodes As Integer
  NO_ERROR = 0
  ERROR_CANCELLED = 1223
  ERROR_NO_SUCH_LOGON_SESSION = 1312
  ERROR_NOT_FOUND = 1168
  ERROR_INVALID_ACCOUNT_NAME = 1315
  ERROR_INSUFFICIENT_BUFFER = 122
  ERROR_INVALID_PARAMETER = 87
  ERROR_INVALID_FLAGS = 1004
  End Enum
  
  Public Structure CREDUI_INFO
  Public cbSize As Integer
  Public hwndParent As IntPtr
   Public pszMessageText As String
   Public pszCaptionText As String
  Public hbmBanner As IntPtr
  End Structure
  
  为 API 调用创建包装函数
  此步骤不是必需的。您可以简单地将 API 声明为 Public(而不是像我的代码一样,使其声明为 Private),并从应用程序中直接调用它们。不过,我发现调用 API 经常需要完成一些工作,因而我喜欢通过包装 API 调用来向代码的最终用户隐藏这些调用细节。
  
  Private Const MAX_USER_NAME As Integer = 100
  Private Const MAX_PASSWORD As Integer = 100
  Private Const MAX_DOMAIN As Integer = 100
  
  Public Shared Function PromptForCredentials( _
     ByRef creditUI As CREDUI_INFO, _
     ByVal targetName As String, _
     ByVal netError As Integer, _
     ByRef userName As String, _
     ByRef password As String, _
     ByRef save As Boolean, _
     ByVal flags As CREDUI_FLAGS) _
  As CredUIReturnCodes
  
  Dim saveCredentials As Integer
  Dim user As New StringBuilder(MAX_USER_NAME)
  Dim pwd As New StringBuilder(MAX_PASSWORD)
  saveCredentials = Convert.ToInt32(save)
  creditUI.cbSize = Marshal.SizeOf(creditUI)
  Dim result As CredUIReturnCodes
  result = CredUIPromptForCredentials( _
          creditUI, targetName, _
          IntPtr.Zero, netError, _
          user, MAX_USER_NAME, _
          pwd, MAX_PASSWORD, _
          saveCredentials, flags)
  save = Convert.ToBoolean(saveCredentials)
  userName = user.ToString
  password = pwd.ToString
  Return result
  End Function
  
  Public Shared Function ParseUserName(ByVal userName As String, _
     ByRef userPart As String, _
     ByRef domainPart As String) _
  As CredUIReturnCodes
  
  Dim user As New StringBuilder(MAX_USER_NAME)
  Dim domain As New StringBuilder(MAX_DOMAIN)
  Dim result As CredUIReturnCodes
  result = CredUIParseUserName(userName, _
    user, MAX_USER_NAME, _
    domain, MAX_DOMAIN)
  userPart = user.ToString()
  domainPart = domain.ToString()
  Return result
  End Function
  
  Public Shared Function ConfirmCredentials(ByVal target As String, _
     ByVal confirm As Boolean) As CredUIReturnCodes
  Return CredUIConfirmCredentials(target, confirm)
  End Function
  
  注:为了便于使用,我已经使我的所有函数都成为 Shared/Static 函数。因为它们没有将任
【责编:admin】
--------------------next---------------------

阅读(1322) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~