2012-07-18 74 views
1

將身份驗證設置爲Windows,並且roleManager正在使用AspNetWindowsTokenRoleProvider。這是一個Intranet應用程序。從角色測試的下拉列表中更改已登錄的用戶

我創建了幾個不同的測試帳戶(本地到Web服務器)來測試應用程序的不同角色。每個用戶都屬於不同的本地組,並且每個組在應用程序中扮演不同的角色。我想爲用戶提供一個選擇選項來在帳戶之間切換。

理想我想有以下類型的用戶選項網頁上的下拉框中選擇:

  • WindowsUser(用戶當前登錄到Windows或挑戰的用戶名/密碼,如果這不能計算出)
  • TestUserForRole1
  • TestUserForRole2
  • TestUserForRole3

如果這是不可能的,接下來最好的方法是提示用戶輸入用戶名/密碼並在服務器上對其進行身份驗證,以使用所提供的憑證建立新的會話。我有什麼選擇?謝謝。

回答

0

我想我想出了這一個。我的解決方案是通過選擇下拉框來設置cookie並刷新頁面。如果需要,請閱讀Application_AuthenticateRequest事件中的cookie值,並用請求的用戶替換HttpContext.User。下面的代碼:

選擇這樣的用戶:

<select id="LoginUser" name="LoginUser" onchange="ChangeLoginUser(this)"> 
    <option value="NONE">-- Change User --</option> 
    <option value="">Windows User</option> 
    <option value="UserOne">User One</option> 
    <option value="UserTwo">User Two</option> 
</select> 

處理與JavaScript(AppPath reference

function ChangeLoginUser(sel) { 
    var selectedUser = sel.options[sel.selectedIndex].value; 
    if (selectedUser == "NONE") return; 
    $.cookie("LoginUser", selectedUser, { path: AppPath }); 
    location.reload(true); //refresh 
} 

當前登錄的Windows用戶與選擇覆蓋用戶選擇:

protected void Application_AuthenticateRequest(Object sender, EventArgs e) 
{ 
    OverrideLoginUser(); 
} 

private void OverrideLoginUser() 
{ 
    HttpCookie authCookie = Context.Request.Cookies["LoginUser"]; 
    if (authCookie == null || string.IsNullOrWhiteSpace(authCookie.Value)) 
     return; //regular authentication 

    if (User != null && User.Username().Equals(authCookie.Value)) 
     return; //already set 

    Context.User = GetTestUser(authCookie.Value); 
} 

private WindowsPrincipal GetTestUser(string user) 
{ 
    WindowsPrincipal testuser = null; 
    IntPtr hToken;     
    if (WinSec.LogonUser(user, "", "ThePassword", // all users have the same password 
     (int)LogonType.LOGON32_LOGON_INTERACTIVE, (int)LogonProvider.LOGON32_PROVIDER_DEFAULT, out hToken)) 
    { 
     testuser = new WindowsPrincipal(new WindowsIdentity(hToken, "WindowsAuthentication")); 
     } 
     if (hToken != IntPtr.Zero) WinSec.CloseHandle(hToken); 
    } 

    if (testuser == null) 
     throw new Exception("Error getting test user"); 

    return testuser; 
} 

用戶名()分機號

public static string Username(this IPrincipal user) 
{ 
    var name = user.Identity.Name; 
    //remove domain name 
    name = Regex.Replace(name, ".*\\\\(.*)", "$1", RegexOptions.None); 
    return name; 
} 

UserLogon功能需要由下面的類來提供

/// <summary> 
/// http://pinvoke.net/default.aspx/advapi32.LogonUser 
/// </summary> 
public class WinSec 
{ 
    [DllImport("advapi32.dll", SetLastError = true)] 
    public static extern bool LogonUser(
     string lpszUsername, 
     string lpszDomain, 
     string lpszPassword, 
     int dwLogonType, 
     int dwLogonProvider, 
     out IntPtr phToken 
    ); 

    [DllImport("advapi32.dll", SetLastError = true)] 
    public extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, out IntPtr DuplicateTokenHandle); 

    [DllImport("kernel32.dll", SetLastError = true)] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    public static extern bool CloseHandle(IntPtr hObject); 
} 

public enum LogonType 
{ 
    /// <summary> 
    /// This logon type is intended for users who will be interactively using the computer, such as a user being logged on 
    /// by a terminal server, remote shell, or similar process. 
    /// This logon type has the additional expense of caching logon information for disconnected operations; 
    /// therefore, it is inappropriate for some client/server applications, 
    /// such as a mail server. 
    /// </summary> 
    LOGON32_LOGON_INTERACTIVE = 2, 

    /// <summary> 
    /// This logon type is intended for high performance servers to authenticate plaintext passwords. 

    /// The LogonUser function does not cache credentials for this logon type. 
    /// </summary> 
    LOGON32_LOGON_NETWORK = 3, 

    /// <summary> 
    /// This logon type is intended for batch servers, where processes may be executing on behalf of a user without 
    /// their direct intervention. This type is also for higher performance servers that process many plaintext 
    /// authentication attempts at a time, such as mail or Web servers. 
    /// The LogonUser function does not cache credentials for this logon type. 
    /// </summary> 
    LOGON32_LOGON_BATCH = 4, 

    /// <summary> 
    /// Indicates a service-type logon. The account provided must have the service privilege enabled. 
    /// </summary> 
    LOGON32_LOGON_SERVICE = 5, 

    /// <summary> 
    /// This logon type is for GINA DLLs that log on users who will be interactively using the computer. 
    /// This logon type can generate a unique audit record that shows when the workstation was unlocked. 
    /// </summary> 
    LOGON32_LOGON_UNLOCK = 7, 

    /// <summary> 
    /// This logon type preserves the name and password in the authentication package, which allows the server to make 
    /// connections to other network servers while impersonating the client. A server can accept plaintext credentials 
    /// from a client, call LogonUser, verify that the user can access the system across the network, and still 
    /// communicate with other servers. 
    /// NOTE: Windows NT: This value is not supported. 
    /// </summary> 
    LOGON32_LOGON_NETWORK_CLEARTEXT = 8, 

    /// <summary> 
    /// This logon type allows the caller to clone its current token and specify new credentials for outbound connections. 
    /// The new logon session has the same local identifier but uses different credentials for other network connections. 
    /// NOTE: This logon type is supported only by the LOGON32_PROVIDER_WINNT50 logon provider. 
    /// NOTE: Windows NT: This value is not supported. 
    /// </summary> 
    LOGON32_LOGON_NEW_CREDENTIALS = 9, 
} 

public enum LogonProvider 
{ 
    /// <summary> 
    /// Use the standard logon provider for the system. 
    /// The default security provider is negotiate, unless you pass NULL for the domain name and the user name 
    /// is not in UPN format. In this case, the default provider is NTLM. 
    /// NOTE: Windows 2000/NT: The default security provider is NTLM. 
    /// </summary> 
    LOGON32_PROVIDER_DEFAULT = 0, 
    LOGON32_PROVIDER_WINNT35 = 1, 
    LOGON32_PROVIDER_WINNT40 = 2, 
    LOGON32_PROVIDER_WINNT50 = 3 
} 

public enum SecurityImpersonationLevel 
{ 
    /// <summary> 
    /// The server process cannot obtain identification information about the client, 
    /// and it cannot impersonate the client. It is defined with no value given, and thus, 
    /// by ANSI C rules, defaults to a value of zero. 
    /// </summary> 
    SecurityAnonymous = 0, 

    /// <summary> 
    /// The server process can obtain information about the client, such as security identifiers and privileges, 
    /// but it cannot impersonate the client. This is useful for servers that export their own objects, 
    /// for example, database products that export tables and views. 
    /// Using the retrieved client-security information, the server can make access-validation decisions without 
    /// being able to use other services that are using the client's security context. 
    /// </summary> 
    SecurityIdentification = 1, 

    /// <summary> 
    /// The server process can impersonate the client's security context on its local system. 
    /// The server cannot impersonate the client on remote systems. 
    /// </summary> 
    SecurityImpersonation = 2, 

    /// <summary> 
    /// The server process can impersonate the client's security context on remote systems. 
    /// NOTE: Windows NT: This impersonation level is not supported. 
    /// </summary> 
    SecurityDelegation = 3, 
}