Domanda

Ho un ASP.NET sito che deve utilizzare l'Autenticazione basata su Form e non l'Autenticazione di Windows per accedere a un ActiveDirectoryMembershipProvider.Il sito è necessario utilizzare le forme, in quanto hanno bisogno di un modulo di input invece di autenticazione del browser pop-up che utilizza l'autenticazione di Windows.

Il sito deve rappresentare l'utente connesso tramite Active Directory per l'accesso utente specifico file.

Tuttavia, l' WindowsIdentity.GetCurrent() non è la stessa come l' HttpContext.Current.User.Identity anche se il mio web.config contiene:

<authentication mode="Forms">
    <forms loginUrl="login.aspx" timeout="480"/>
</authentication>
<identity impersonate="true" />

Non posso usare LoginUser() e il WindowsIdentity.Impersonate() perché ho bisogno di spacciarsi per esempio AD un utente per ottenere le loro specifiche autorizzazioni, e non so la password dell'utente, perché le Forme si prende cura di accesso.

È possibile, forse, dal login.aspx.cs, per prendere il System.Web.UI.WebControls.Login.Password, quindi , salvare la LoginUser() token in una variabile di sessione per WindowsIdentity.Impersonate() più tardi?O forse un modo molto più sicuro di rappresentare la strada giusta?

Sono confuso perché le Forme di autenticazione non può automaticamente <identity impersonate="true" />

Ho letto questo http://msdn.microsoft.com/en-us/library/ms998351.aspx ma si utilizza l'Autenticazione di Windows.

È stato utile?

Soluzione

rappresentazione di un utente utilizzando i moduli di autenticazione può essere fatto. Il codice seguente funziona .

Il visiva articolo Studio Magazine cui Robert è una risorsa eccellente. Ci sono alcuni problemi con il codice di esempio in questo articolo, quindi ho incluso un codice di lavoro al di sotto.

. Nota: Se si utilizza Visual Studio, assicuratevi di lanciarlo " Esegui come amministratore " per evitare problemi con UAC blocco rappresentazione

// in your login page (hook up to OnAuthenticate event)
protected void LoginControl_Authenticate(object sender, AuthenticateEventArgs e)
{
    int token;
    // replace "YOURDOMAIN" with your actual domain name
    e.Authenticated = LogonUser(LoginUser.UserName,"YOURDOMAIN",LoginUser.Password,8,0,out token);
    if (e.Authenticated) {
        Session.Add("principal", new WindowsPrincipal(new WindowsIdentity(new IntPtr(token))));
    }
}

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


// in global.asax.cs
void Application_PreRequestHandlerExecute(object send, EventArgs e)
{
    if (Thread.CurrentPrincipal.Identity.IsAuthenticated == true && HttpContext.Current.Session != null) {
        WindowsPrincipal windowsPrincipal = (WindowsPrincipal)Session["principal"];
        Session["principal"] = (GenericPrincipal)Thread.CurrentPrincipal;
        Thread.CurrentPrincipal = windowsPrincipal;
        HttpContext.Current.User = windowsPrincipal;
        HttpContext.Current.Items["identity"] = ((WindowsIdentity)windowsPrincipal.Identity).Impersonate();
    }
}

// in global.asax.cs
void Application_PostRequestHandlerExecute(object send, EventArgs e)
{
    if (HttpContext.Current.Session != null && Session["principal"] as GenericPrincipal != null) {
        GenericPrincipal genericPrincipal = (GenericPrincipal)Session["principal"];
        Session["principal"] = (WindowsPrincipal)Thread.CurrentPrincipal;
        Thread.CurrentPrincipal = genericPrincipal;
        HttpContext.Current.User = genericPrincipal;
        ((WindowsImpersonationContext)HttpContext.Current.Items["identity"]).Undo();
    }
}

// test that impersonation is working (add this and an Asp:Label to a test page)
protected void Page_Load(object sender, EventArgs e)
{
    try {
        // replace YOURSERVER and YOURDB with your actual server and database names
        string connstring = "data source=YOURSERVER;initial catalog=YOURDB;integrated security=True";
        using (SqlConnection conn = new SqlConnection(connstring)) {
            conn.Open();
            SqlCommand cmd = new SqlCommand("SELECT SUSER_NAME()", conn);
            using (SqlDataReader rdr = cmd.ExecuteReader()) {
                rdr.Read();
                Label1.Text = "SUSER_NAME() = " + rdr.GetString(0);
            }
        }
    }
    catch {
    }
}

Aggiornamento:

Si dovrebbe anche gestire Application_EndRequest, perché chiamate come Response.End() saranno bypassare Application_PostRequestHandlerExecute.

Un altro problema è che la WindowsIdentity può ottenere garbage collection, così si dovrebbe creare un nuovo WindowsIdentity e WindowsPrincipal dal token di accesso a ogni richiesta.

Update2:

Non sono sicuro perché questo è sempre downvoted, perché funziona. Ho aggiunto la firma PInvoke e qualche codice di prova. Anche in questo caso, il lancio di Visual Studio con " Esegui come amministratore ". Google come fare se non si sa come.

Altri suggerimenti

Se gli utenti utilizzano IE allora si può attivare la protezione integrata per il sito web e gli utenti saranno autenticati in silenzio (senza finestra di login, nessuna pagina di login). La vostra rappresentazione sarà poi lavorare. Se avete bisogno di indirizzare gli altri browser, allora questo non può funzionare (l'utente sarà probabilmente presentato con una finestra di accesso).

Il tuo attuale rappresentazione non funzionerà mai perché i vostri utenti accedono utilizzando un account diverso dal loro account di dominio. Non si può pretendere il sito per rappresentare un utente che non ha fornito le sue credenziali. Sarebbe andare contro entità di protezione di base.

È possibile trovare questo utile:

Modifica

Dopo aver letto la tua domanda più da vicino, non sono sicuro se questo approccio potrebbe funzionare con il vostro scenario però; quando si effettua il login usando le forme di autenticazione e di rappresentare l'utente di Active Directory

Abbiamo avuto lo stesso problema da poco, il cliente ha voluto i loro utenti possono accedere per conto dC e poi questa credenziale deve essere utilizzato per accedere Servizio Analisi così come tutti gli altri database. Volevano in questo modo perché implementato un sistema di controllo e tutti gli accessi devono essere eseguite da effettuato corrente in conto.

Abbiamo provato autenticazione basata su form e Win32 LogonUser () API per impersonare parte, ha funzionato ma ci chiede anche la password dell'utente come testo normale. Più tardi, abbiamo deciso di autenticazione di Windows utilizzata, ci fa risparmiare molto tempo (non più di autenticazione AD, impersonare manualmente). Naturalmente, c'era anche nessuna pagina di login di fantasia.

Per ogni evenienza, e un po 'tardi, ho trovato qualcosa che funziona per me ed è davvero semplice, ma, naturalmente, è solo a scopo di test ...

È sufficiente impostare un cookie con il tuo nome utente.

//Login button. You can give whatever input to the form
protected void Login_Click(object sender, EventArgs e)
{
    FormsAuthentication.SetAuthCookie("your_username", createPersistentCookie: true);
    Response.Redirect("~/");
}

Qualsiasi commento accettate ...

In Visual Studio installare NuGet Apri la tua soluzione

Poi nella confezione della console di eseguire il Pacchetto di Installazione 51Degrees.mobi

Sarà poi aggiungere 51Degrees al tuo sito web.È quindi possibile modificare il 51Degrees.mobi.config App Dati per rimuovere il redirect sezione.

Ora, hai aggiornato le funzionalità del browser

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top