2014-02-06 17 views
1

我已經創建了使用IWA的asp.net(vb.net)網站。完全沒有問題。使用ASP.NET時如何模擬Windows Credentials?

但是,現在我擁有的用戶不一定是我公司域的一部分,但需要登錄我的網絡才能訪問公共信息。

我在我的AD上創建了一個公共賬戶。我想要做的是,當外部用戶登錄時,能夠傳遞公共賬戶憑據,以便他們可以訪問公共信息。

這可能嗎?

回答

0

您可以臨時模擬用戶:

在C#

,但你可以很容易將其翻譯成VB

if (!HttpContext.Current.User.Identity.IsAuthenticated) 
    { 
     if (LogonUser("TempUser", Environment.MachineName, 
        "password", LOGON32_LOGON_INTERACTIVE, 
        LOGON32_PROVIDER_DEFAULT, ref token) != 0) 
     { 
      if (DuplicateToken(token, SecurityImpersonation, ref tokenDuplicate) != 0) 
      { 
      m_ImpersonatedUser = new WindowsIdentity(tokenDuplicate); 
      m_ImpersonationContext = m_ImpersonatedUser.Impersonate();         
      try 
      { 
       // impersonated code here  
      }   
      catch { throw; } 
      finally 
      { 
       m_ImpersonationContext.Undo(); 
      } 
      } 
     } 
    } 
1

你可以使用身份模擬在web.config設置設置憑據:

<system.web> 
    <authentication mode="Windows"/> 
    <identity impersonate="true" userName="foo" password="bar"/> 
</system.web> 

,使密碼不存儲在明文你也應該加密的web.config。 http://msdn.microsoft.com/en-us/library/89211k9b.aspx

另一種選擇是讓您的用戶能夠在代碼中模擬您的服務帳戶。請注意,這個代碼在C#中,但我寫它爲飛行Windows模仿。它可以被編譯成一個DLL和引用在VB.NET:

/// <summary> 
/// Facilitates impersonation of a Windows User. 
/// </summary> 
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")] 
public class Impersonation : IDisposable 
{ 
    public string Environment { get; set; } 

    public string UserName { get; set; } 

    public string Password { get; set; } 

    public string DomainName { get; set; } 

    public enum LogonType 
    { 
     Interactive = 2, 
     Network = 3, 
     Batch = 4, 
     Service = 5, 
     Unlock = 7, 
     NetworkClearText = 8, 
     NewCredentials = 9 
    } 

    public enum LogonProvider 
    { 
     Default = 0, 
     WinNT35 = 1, 
     WinNT40 = 2, 
     WinNT50 = 3 
    } 

    /// <summary> 
    /// Windows Token. 
    /// </summary> 
    private readonly SafeTokenHandle _handle; 

    /// <summary> 
    /// The impersonated User. 
    /// </summary> 
    private WindowsImpersonationContext impersonatedUser; 

    public Impersonation() 
    { 
    } 

    /// <summary> 
    /// Initializes a new instance of the Impersonation class. Provides domain, user name, and password for impersonation. 
    /// </summary> 
    /// <param name="domainName">Domain name of the impersonated user.</param> 
    /// <param name="userName">Name of the impersonated user.</param> 
    /// <param name="password">Password of the impersonated user.</param> 
    /// <remarks> 
    /// Uses the unmanaged LogonUser function to get the user token for 
    /// the specified user, domain, and password. 
    /// </remarks> 
    public Impersonation(AccountCredentials credentials) 
    {    
     string[] splitName = WindowsIdentity.GetCurrent().Name.Split('\\'); 
     string name = (splitName.Length > 0) ? splitName[0] : null; 

     LogonType logonType = LogonType.Interactive; 
     LogonProvider logonProvider = LogonProvider.Default; 

     if (name != credentials.Domain) 
     { 
      logonType = LogonType.NewCredentials; 
      logonProvider = LogonProvider.WinNT50; 
     } 

     // Call LogonUser to obtain a handle to an access token. 
     bool returnValue = LogonUser(
          credentials.UserName, 
          credentials.Domain, 
          credentials.Password, 
          (int)logonType, 
          (int)logonProvider, 
          out this._handle); 

     if (!returnValue) 
     { 
      // Something went wrong. 
      int ret = Marshal.GetLastWin32Error(); 
      throw new System.ComponentModel.Win32Exception(ret); 
     } 

     this.impersonatedUser = WindowsIdentity.Impersonate(this._handle.DangerousGetHandle());  
    } 

    /// <summary> 
    /// Initializes a new instance of the Impersonation class. Provide domain, user name, and password for impersonation. 
    /// </summary> 
    /// <param name="domainName">Domain name of the impersonated user.</param> 
    /// <param name="userName">Name of the impersonated user.</param> 
    /// <param name="password">Password of the impersonated user.</param> 
    /// <remarks> 
    /// Uses the unmanaged LogonUser function to get the user token for 
    /// the specified user, domain, and password. 
    /// </remarks> 
    public Impersonation(string domainName, string userName, string password) 
    { 
     string[] splitName = WindowsIdentity.GetCurrent().Name.Split('\\'); 
     string name = (splitName.Length > 0) ? splitName[0] : null; 

     LogonType logonType = LogonType.Interactive; 
     LogonProvider logonProvider = LogonProvider.Default; 

     if (name != domainName) 
     { 
      logonType = LogonType.NewCredentials; 
      logonProvider = LogonProvider.WinNT50; 
     } 

     // Call LogonUser to obtain a handle to an access token. 
     bool returnValue = LogonUser(
          userName, 
          domainName, 
          password, 
          (int)logonType, 
          (int)logonProvider, 
          out this._handle); 

     if (!returnValue) 
     { 
       // Something went wrong. 
      int ret = Marshal.GetLastWin32Error(); 
      throw new System.ComponentModel.Win32Exception(ret); 
     } 

     this.impersonatedUser = WindowsIdentity.Impersonate(this._handle.DangerousGetHandle()); 
    } 

    [DllImport("advapi32.dll", SetLastError = true)] 
    private static extern bool LogonUser(
      string lpszUsername, 
      string lpszDomain, 
      string lpszPassword, 
      int dwLogonType, 
      int dwLogonProvider, 
      out SafeTokenHandle phToken); 

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)] 
    private static extern bool CloseHandle(IntPtr handle); 

    public void Dispose() 
    { 
     this.impersonatedUser.Dispose(); 
     this._handle.Dispose(); 
    } 

    private static string[] GetAccountInfo(string accountInfo) 
    { 
     return accountInfo.Split(' '); 
    } 
} 

public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid 
{ 
    private SafeTokenHandle() 
     : base(true) { } 

    [DllImport("kernel32.dll")] 
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
    [SuppressUnmanagedCodeSecurity] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    private static extern bool CloseHandle(IntPtr handle); 

    protected override bool ReleaseHandle() 
    { 
     return CloseHandle(handle); 
    } 
} 

public class AccountCredentials 
{ 
    public string UserName { get; set; } 
    public string Password { get; set; } 
    public string Domain { get; set; } 
} 

然後你會做一個使用塊你模擬的動作:

using(new Impersonation(new AccountCredentials("user", "password", "domain")) 
{ 
    // do impersonated actions 
} 

您必須使用這些指令在類:

using System; 
using System.Runtime.InteropServices; 
using System.Security.Permissions; 
using System.Security.Principal; 
using Microsoft.Win32.SafeHandles; 
using System.Runtime.ConstrainedExecution; 
using System.Security; 
using System.Configuration; 
+1

這將使他的所有用戶都承擔這個Windows憑據,這不是他所需要的。他正在研究某種混合模式身份驗證,網絡內的用戶使用他們的憑據,但外部用戶應使用所有相同的帳戶。 – tucaz

+1

我添加了用於在飛行模擬中執行的代碼。它是用C#編寫的,但可以在VB.NET中作爲DLL引用。 –

0

了翔實的答案謝謝你們......對不起,找回這麼晚了......所以,我現在所做的就是這個....

進口System.Web.Security

進口System.Security.Principal

進口System.Security.Permissions

進口System.Runtime.InteropServices

進口統環境

公共類重定向 繼承System.Web.UI.Page

Dim LOGON32_LOGON_INTERACTIVE As Integer = 2 
Dim LOGON32_PROVIDER_DEFAULT As Integer = 0 

Dim impersonationContext As WindowsImpersonationContext 

Declare Function LogonUserA Lib "advapi32.dll" (ByVal lpszUsername As String, _ 
         ByVal lpszDomain As String, _ 
         ByVal lpszPassword As String, _ 
         ByVal dwLogonType As Integer, _ 
         ByVal dwLogonProvider As Integer, _ 
         ByRef phToken As IntPtr) As Integer 

Declare Auto Function DuplicateToken Lib "advapi32.dll" (_ 
         ByVal ExistingTokenHandle As IntPtr, _ 
         ByVal ImpersonationLevel As Integer, _ 
         ByRef DuplicateTokenHandle As IntPtr) As Integer 

Declare Auto Function RevertToSelf Lib "advapi32.dll"() As Long 
Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Long 

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
    Dim redirstr As Integer 
    redirstr = Request.QueryString("id") 
    If impersonateValidUser("*username*", "*Domain*", "*Password*") Then 
     'Insert your code that runs under the security context of a specific user here. 

     Try 
      'Integrated Windows Authentication Site 
      Response.Redirect("http://<<servername>>/<app>/<<file>") 

     Catch ex As Exception 

     End Try 
     undoImpersonation() 
    Else 
     'Your impersonation failed. Therefore, include a fail-safe mechanism here. 
    'Not Integrated Windows Authentication Site 
     Response.Redirect("http://<<servername>>:81/<app>/<<file>?user=<<username>>&pass=<<password>>) 
    End If 

End Sub 

Private Function impersonateValidUser(ByVal userName As String, _ 
ByVal domain As String, ByVal password As String) As Boolean 

    Dim tempWindowsIdentity As WindowsIdentity 
    Dim token As IntPtr = IntPtr.Zero 
    Dim tokenDuplicate As IntPtr = IntPtr.Zero 
    impersonateValidUser = False 

    If RevertToSelf() Then 
     If LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, 
        LOGON32_PROVIDER_DEFAULT, token) <> 0 Then 
      If DuplicateToken(token, 2, tokenDuplicate) <> 0 Then 
       tempWindowsIdentity = New WindowsIdentity(tokenDuplicate) 
       impersonationContext = tempWindowsIdentity.Impersonate() 
       If Not impersonationContext Is Nothing Then 
        impersonateValidUser = True 
       End If 
      End If 
     End If 
    End If 
    If Not tokenDuplicate.Equals(IntPtr.Zero) Then 
     CloseHandle(tokenDuplicate) 
    End If 
    If Not token.Equals(IntPtr.Zero) Then 
     CloseHandle(token) 
    End If 
End Function 

Private Sub undoImpersonation() 
    impersonationContext.Undo() 
End Sub 

末級

所以在這種情況下,理想的應該傳遞行動的IWA網站,如果我的身份驗證通過它的確如此,但是一旦我進入IWA網站,就需要我的Windows憑據,而不是我想要模仿的那個。我如何實現這一點...哪裏可以使用我的模擬的Windows用戶憑據去網站?

相關問題