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

Где создать пользовательский идентификатор с WIF в приложении MVC?

До WIF Application_PostAcquireRequestState было хорошим местом для создания персонализированного идентификатора, но требовалось много фреймворков, чтобы убедиться, что каждый тип аутентификации, который вы делали, был соответствующим образом сопоставлен. По индивидуальному идентификатору я имею в виду класс, наследующий от Identity, например, ниже SomeIdentity, так что у нас может быть определенное свойство, которое может потребоваться для всех пользователей, прошедших проверку подлинности.

PostAcquirerequestState по-прежнему доступен, но есть много новых способов, с помощью которых можно подключиться к аутентификации. Кроме того, старые методы становятся сложными при поддержке нескольких методов проверки подлинности.

Я хотел бы узнать, есть ли лучший способ, чем ниже, чтобы выполнить это сейчас в WIF. Прежде всего, я хотел бы выделить код, который обрабатывает заявки на идентификацию. Идея заключается в том, что код будет другим для других типов/поставщиков аутентификации, поскольку способ получения этого значения свойства может быть не от требования, такого как с SAML, а из другого места для других методов проверки подлинности. Я использую Kentor.AuthServices для поддержки SAML в настоящее время. Хотя может быть другой код для сопоставления этих значений в зависимости от поставщика, конечным результатом будет то, что был создан экземпляр SomeIdentity, и он установит SomeProperty и другие свойства. Таким образом, остальная часть приложения всегда может зависеть/предполагать, что они были обработаны.

В моем проекте MVC появился AccountController, у которого был ExternalLoginCallback, который, как подразумевалось, может быть хорошим крюком для завершения внешней аутентификации (что для меня SAML является "внешней" аутентификацией). Тем не менее, он не кажется пораженным ни в какой момент во время/после аутентификации SAML.

Может быть, ответ заключается в том, что нам все равно нужно собрать это вместе по-старому, но я надеялся, что у WIF есть несколько лучших фреймворков, чтобы сделать это проще.

public sealed class SomeIdentity : Identity
{
  ...
  // Some custom properties
  public string SomeProperty { get;set;}
}

protected void Application_PostAcquireRequestState(object sender, EventArgs e)
{
  ...
  identity = new SomeIdentity(id, userId);
  // map a claim to a specific property
  identity.SomeProperty = ...Claims[IdpSomePropertyKey];
  ///...

  GenericPrincipal newPrincipal = new GenericPrincipal(identity , null);
  HttpContext.Current.User = newPrincipal;
  System.Threading.Thread.CurrentPrincipal = newPrincipal;
}

Теперь, когда я использую WIF, где я должен помещать код, специфичный для определенного типа аутентификации (т.е. Kentor.AuthServices SAML), который создает пользовательскую функцию SomeIdentity?

Идея заключается в том, что SomeIdentity будет классом идентификации, используемым повсюду в моем приложении, но код для заполнения его свойств должен быть написан специально для каждого типа проверки подлинности, например, с помощью SAML, чтобы тянуть заявки и использовать их значения для установки proeprties. То есть где происходит отображение.

4b9b3361

Ответ 1

Хорошо, я собираюсь взять укол в этом, и, надеюсь, я понимаю ваш вопрос и не делаю слишком много предположений о вашем коде. Предположения, которые я собираюсь сделать, это новое приложение MVC, созданное с использованием шаблона Visual Studio ASP.NET 4.6 с опцией "Нет аутентификации" (судя по тому, что я понимаю о вашей ситуации, вы не хотите хранить эти данные так же, как просто прочитать его из формулы).

Добавить класс под названием "Начат" в корень вашего проекта

using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(WebApplication1.Startup))]

namespace WebApplication1
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
        }
    }
}

Теперь это будет запущено, как вы, вероятно, можете догадаться, о "запуске", как это делает файл global.asax.cs.

Теперь нам нужно сделать метод ConfigureAuth(). Обычно это делается в папке App_Start с файлом под названием "Startup.Auth.cs". Этот файл в настоящее время не существует, поэтому продолжайте и создайте его с помощью этого шаблона

using Owin;
using Kentor.AuthServices.Owin;

namespace WebApplication1
{
    public partial class Startup
    {
        private void ConfigureAuth(IAppBuilder app)
        {
        }
    }
}

Здесь мы собираемся выполнить логику/настройки аутентификации. OWIN поставляется с довольно много из коробки, стратегий аутентификации, и есть еще несколько библиотек. Я рекомендую взглянуть на OwinOAuthProviders, если вы собираетесь писать свои собственные.

Идем дальше и устанавливаем пакет и зависимости NuGet пакета Kentor.AuthServices.Owin. Это должно исправить любые ошибки компиляции, которые у вас есть на данный момент. Вам также нужно будет добавить ссылку на System.IdentityModel для вашего проекта позже.

Теперь, в вашем методе ConfigureAuth внутри Startup.Auth.cs, вы можете добавить Kentor в свое приложение, выполнив следующие действия.

Public void ConfigureAuth(IAppBuilder app)
{
    var kentorOptions = new KentorAuthServicesAuthenticationOptions(true);
}

Теперь ваша переменная kentorOptions, поскольку я передал ее true, будет читать ваши настройки с вашего WebConfig. Вы также можете настроить их здесь вручную, но.

Интересующая нас часть - свойство kentorOptions.SPOptions.SystemIdentityModelIdentityConfiguration.ClaimsAuthenticationManager. Мы хотим создать пользовательский ClaimsAuthenticationManager, чтобы предоставить идентификатор на основе входящих требований.

Создайте новый класс, который наследуется от ClaimsAuthenticationManager

using System.Security.Claims;

namespace WebApplication5 {
    public class CustomClaimsAuthManager : ClaimsAuthenticationManager {
        public override ClaimsPrincipal Authenticate( string resourceName, ClaimsPrincipal incomingPrincipal ) {
            ClaimsIdentity ident = (ClaimsIdentity) incomingPrincipal.Identity;
            //Use incomingPrincipal.Identity.AuthenticationType to determine how they got auth'd
            //Use incomingPrincipal.Identity.IsAuthenticated to make sure they are authenticated.
            //Use ident.AddClaim to add a new claim to the user
             ...
            identity = new SomeIdentity( id, userId );
            // map a claim to a specific property
            identity.SomeProperty = ...Claims[IdpSomePropertyKey];
            ///...

            GenericPrincipal newPrincipal = new GenericPrincipal( identity, null );
            return newPrincipal;
        }
    }
}

То, что у вас есть свой идентификационный код. Теперь, наконец, нам нужно установить это как приложение ClaimsAuthenticationManager для фактического использования и сообщить вашему приложению использовать Kentor в конвейере OWIN. Все это возвращается в файл Startup.Auth.cs.

private void ConfigureAuth( IAppBuilder app ) {
            var kentorOptions = new KentorAuthServicesAuthenticationOptions(true);
            kentorOptions.SPOptions.SystemIdentityModelIdentityConfiguration.ClaimsAuthenticationManager = new WebApplication5.CustomClaimsAuthManager();
            app.UseKentorAuthServicesAuthentication( kentorOptions );
        }

Эннндд, который, надеюсь, сделает это! Для других поставщиков Auth, таких как OwinOAuthProviders, вы также можете манипулировать вещами, переопределяя параметры. Способы передачи вещей для разных событий, например:

var cookieOptions = new CookieAuthenticationOptions {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString( "/Auth/Login" ),
                CookieName = "cooooookiees",
                ExpireTimeSpan = new TimeSpan( 10000, 0, 0, 0, 0 ),
                Provider = new CookieAuthenticationProvider {
                    OnException = context => {
                        var x = context;
                    },
                    OnValidateIdentity = async context => {
                        var invalidateBySecurityStamp = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                        validateInterval: TimeSpan.FromMinutes( 15 ),
                        regenerateIdentity: ( manager, user ) => user.GenerateUserIdentityAsync( manager ) );
                        await invalidateBySecurityStamp.Invoke( context );

                        if ( context.Identity == null || !context.Identity.IsAuthenticated ) {
                            return;
                        }
                        var newResponseGrant = context.OwinContext.Authentication.AuthenticationResponseGrant;
                        if ( newResponseGrant != null ) {
                            newResponseGrant.Properties.IsPersistent = true;
                        }

                    }
                }
            };
            app.UseCookieAuthentication( cookieOptions );