Подтвердить что ты не робот

Выдавать себя за использование проверки подлинности с помощью форм

У меня есть сайт ASP.NET, который должен использовать аутентификацию по формам, а не проверку подлинности Windows, чтобы получить доступ к ActiveDirectoryMembershipProvider. Сайт должен использовать формы, потому что им нужна разработанная форма ввода вместо всплывающего окна проверки подлинности браузера, используемого для проверки подлинности Windows.

Сайт должен выдавать себя за пользователя, зарегистрированного через Active Directory, для доступа к конкретным файлам пользователя.

Однако WindowsIdentity.GetCurrent() не совпадает с HttpContext.Current.User.Identity, хотя мой файл web.config содержит:

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

Я не могу использовать LoginUser() и WindowsIdentity.Impersonate(), потому что мне нужно выдавать себя за то, что пользователь AD получил свои конкретные разрешения, и я не знаю пароль пользователя, потому что Forms заботится о регистрации.

Возможно ли, может быть, из login.aspx.cs взять System.Web.UI.WebControls.Login.Password, а затем сохранить токен LoginUser() в переменной сеанса для WindowsIdentity.Impersonate() позже? Или, может быть, гораздо более безопасный способ олицетворения правильного пути?

Я смущен, почему автоматическая аутентификация не может автоматически <identity impersonate="true" />

Я прочитал этот http://msdn.microsoft.com/en-us/library/ms998351.aspx, но он использует проверку подлинности Windows.

4b9b3361

Ответ 1

Можно выполнить олицетворение пользователя с использованием проверки подлинности с помощью форм. Следующий код работает.

Статья в Visual Studio Magazine, на которую ссылается Роберт, - отличный ресурс. Есть некоторые проблемы с примером кода в статье, поэтому я включил некоторый рабочий код ниже.

Примечание. Если вы используете Visual Studio, обязательно запустите его " Запуск от имени администратора", чтобы избежать проблем с олицетворением блокировки UAC.

// 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 {
    }
}

Update:

Вы также должны обрабатывать Application_EndRequest, потому что вызовы типа Response.End() будут обходить Application_PostRequestHandlerExecute.

Другая проблема заключается в том, что WindowsIdentity может получить сбор мусора, поэтому вы должны создать новый WindowsIdentity и WindowsPrincipal из токена входа в каждый запрос.

Update2:

Я не уверен, почему это происходит, потому что оно работает. Я добавил подпись pinvoke и некоторый тестовый код. Снова запустите Visual Studio, используя " Запуск от имени администратора". Google, как это сделать, если вы не знаете, как это сделать.

Ответ 2

Если ваши пользователи используют IE, то вы можете включить интегрированную защиту для веб-сайта, и ваши пользователи будут аутентифицироваться молча (нет диалогового окна входа в систему, нет страницы входа). Тогда ваше олицетворение будет работать. Если вам нужно настроить таргетинг на другие браузеры, тогда это может не сработать (пользователю, вероятно, будет представлено диалоговое окно входа в систему).

Ваше текущее олицетворение никогда не будет работать, потому что ваши пользователи регистрируются в учетной записи, отличной от учетной записи домена. Вы не можете ожидать, что сайт выдаст себя за пользователя, который не предоставил свои учетные данные. Это будет противоречить основным принципам безопасности.

Ответ 3

Вы можете найти это полезным:

ИЗМЕНИТЬ

Внимательно прочитав ваш вопрос, я не уверен, что этот подход будет работать с вашим сценарием; при входе в систему с использованием проверки подлинности с использованием форм и персонализации пользователя Active Directory

Ответ 4

В последнее время мы столкнулись с такой же проблемой, что клиент хотел, чтобы их пользователи могли регистрироваться в учетной записи AD, а затем эти учетные данные должны использоваться для доступа к Analysis Service, а также ко всем другим базам данных. Они так хотели, потому что они внедрили систему аудита, и весь доступ должен выполняться с помощью текущей учетной записи.

Мы попробовали аутентификацию форм и API-интерфейс Win32 LogonUser() для выдачи себя за работу, но он также запросил у нас пароль пользователя как обычный текст. Позже мы решили использовать проверку подлинности Windows, это экономит нам много времени (не более аутентификации AD, выдавать себя вручную). Разумеется, также не было никакой привлекательной страницы входа.

Ответ 5

На всякий случай, и немного поздно, я нашел что-то, что работает для меня, и это действительно просто, но, конечно, только для целей тестирования...

Просто установите cookie с вашим именем пользователя.

//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("~/");
}

Любые принятые комментарии...

Ответ 6

В Visual Studio установите NuGet Откройте свое решение

Затем в консоли пакета запустите Install-Package 51Degrees.mobi

Затем он добавит 51Degrees на ваш сайт. Затем вы можете отредактировать файл 51Degrees.mobi.config в своих данных приложения, чтобы удалить раздел перенаправления.

Теперь у вас есть современные возможности браузера.