如何在asp.net Core 1.0.0中获得IOwinContext

本文关键字:IOwinContext Core asp net | 更新日期: 2023-09-27 17:53:08

我在AspNetCore MVC 1.0.0中使用Owin和UseWsFederationAuthentication()。app.身份验证工作完美,但不能退出用户。

这段代码

public class AccountController : Controller
{
    public async Task<IActionResult> SignOut()
    {
        await this.HttpContext.Authentication.SignOutAsync(CookieAuthenticationDefaults.AuthenticationType);
        return RedirectToAction("Index", "Test");
    }
}

抛出:

InvalidOperationException:没有配置认证处理程序来处理方案:Cookies

设置HttpContext.AuthenticationMicrosoft.AspNetCore.Http.Authentication.Internal.DefaultAuthenticationManager

Startup.cs:配置

        app.UseOwinAppBuilder(builder =>
        {
            var authConfig = new WsFederationAuthenticationSettings
            {
                MetadataAddress = this.Configuration.GetValue<string>("Eyc.Sdk:Authentication:WsFederation:MetadataAddress"),
                Realm = this.Configuration.GetValue<string>("Eyc.Sdk:Authentication:WsFederation:Realm"),
                UseCookieSlidingExpiration = this.Configuration.GetValue<bool>("Eyc.Sdk:Authentication:WsFederation:UseCookieSlidingExpiration"),
                CookieExpireTimeSpan = this.Configuration.GetValue<string>("Eyc.Sdk:Authentication:WsFederation:CookieExpireTimeSpan")
            };
            builder.UseEycAuthentication(authConfig, app.ApplicationServices);
        });

public static class ApplicationBuilderExtensions
{
    public static IApplicationBuilder UseOwinAppBuilder(this IApplicationBuilder app, Action<global::Owin.IAppBuilder> configuration)
    {
        return app.UseOwin(setup => setup(next =>
        {
            var builder = new AppBuilder();
            var lifetime = (IApplicationLifetime)app.ApplicationServices.GetService(typeof(IApplicationLifetime));
            var properties = new AppProperties(builder.Properties);
            properties.AppName = app.ApplicationServices.GetApplicationUniqueIdentifier();
            properties.OnAppDisposing = lifetime.ApplicationStopping;
            properties.DefaultApp = next;
            configuration(builder);
            return builder.Build<Func<IDictionary<string, object>, Task>>();
        }));
    }
}

public static class AppBuilderExtensions
{
    public static IAppBuilder UseEycAuthentication(
        this IAppBuilder app,
        WsFederationAuthenticationSettings authenticationSettings,
        IServiceProvider serviceProvider,
        bool authenticateEveryRequest = true)
    {
        if (app == null)
        {
            throw new ArgumentNullException(nameof(app));
        }
        if (authenticationSettings == null)
        {
            throw new ArgumentNullException(nameof(authenticationSettings));
        }
        if (serviceProvider == null)
        {
            throw new ArgumentNullException(nameof(serviceProvider));
        }
        return app.ConfigureWsFederationAuthentication(serviceProvider, authenticationSettings, authenticateEveryRequest);
    }
    private static IAppBuilder ConfigureWsFederationAuthentication(
        this IAppBuilder app,
        IServiceProvider serviceProvider,
        WsFederationAuthenticationSettings authenticationSettings,
        bool authenticateEveryRequest = true)
    {
        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
        app.UseCookieAuthentication(
                new CookieAuthenticationOptions
                {
                    SlidingExpiration = authenticationSettings.UseCookieSlidingExpiration,
                    ExpireTimeSpan = authenticationSettings.GetCookieExpireTimeSpan()
                });
        var wsFederationAuthenticationOptions = GetWsFederationAuthenticationOptions(authenticationSettings);
        app.UseWsFederationAuthentication(wsFederationAuthenticationOptions);
        var eycAuthenticationManager = (IEycAuthenticationManager)serviceProvider.GetService(typeof(IEycAuthenticationManager));
        app.Use<EycAuthenticationOwinMiddleware>(eycAuthenticationManager);
        // http://stackoverflow.com/questions/23524318/require-authentication-for-all-requests-to-an-owin-application
        if (authenticateEveryRequest)
        {
            app.Use(async (owinContext, next) =>
            {
                var user = owinContext.Authentication.User;
                if (!(user?.Identity?.IsAuthenticated ?? false))
                {
                    owinContext.Authentication.Challenge();
                    return;
                }
                await next();
            });
        }
        return app;
    }
    private static WsFederationAuthenticationOptions GetWsFederationAuthenticationOptions(WsFederationAuthenticationSettings settings)
    {
        var wsFederationAuthenticationNotifications = GetWsFederationAuthenticationNotifications(settings);
        var wsFederationAuthenticationOptions = new WsFederationAuthenticationOptions
        {
            Wtrealm = settings.Realm,
            MetadataAddress = settings.MetadataAddress,
            TokenValidationParameters = new TokenValidationParameters
            {
                ValidAudiences = settings.Realms
            },
            Notifications = wsFederationAuthenticationNotifications
        };
        if (settings.UseCookieSlidingExpiration)
        {
            // this needs to be false for sliding expiration to work
            wsFederationAuthenticationOptions.UseTokenLifetime = false;
        }
        return wsFederationAuthenticationOptions;
    }
    private static WsFederationAuthenticationNotifications GetWsFederationAuthenticationNotifications(WsFederationAuthenticationSettings settings)
    {
        var wsFederationAuthenticationNotifications = new WsFederationAuthenticationNotifications();
        wsFederationAuthenticationNotifications.AuthenticationFailed = settings.AuthenticationFailed ?? wsFederationAuthenticationNotifications.AuthenticationFailed;
        wsFederationAuthenticationNotifications.MessageReceived = settings.MessageReceived ?? wsFederationAuthenticationNotifications.MessageReceived;
        wsFederationAuthenticationNotifications.RedirectToIdentityProvider = settings.RedirectToIdentityProvider ?? wsFederationAuthenticationNotifications.RedirectToIdentityProvider;
        wsFederationAuthenticationNotifications.SecurityTokenReceived = settings.SecurityTokenReceived ?? wsFederationAuthenticationNotifications.SecurityTokenReceived;
        wsFederationAuthenticationNotifications.SecurityTokenValidated = settings.SecurityTokenValidated ?? wsFederationAuthenticationNotifications.SecurityTokenValidated;
        return wsFederationAuthenticationNotifications;
    }
}

public class EycAuthenticationOwinMiddleware : OwinMiddleware
{
    private readonly IEycAuthenticationManager _eycAuthenticationManager;
    #region ctors
    public EycAuthenticationOwinMiddleware(OwinMiddleware next, IEycAuthenticationManager eycAuthenticationManager)
        : base(next)
    {
        if (eycAuthenticationManager == null)
        {
            throw new ArgumentNullException(nameof(eycAuthenticationManager));
        }
        this._eycAuthenticationManager = eycAuthenticationManager;
    }
    #endregion
    public override Task Invoke(IOwinContext context)
    {
        if (context.Authentication.User != null)
        {
            context.Authentication.User =
                this._eycAuthenticationManager.Authenticate(
                    context.Request.Uri.AbsoluteUri,
                    context.Authentication.User);
        }
        return this.Next.Invoke(context);
    }
}

public class EycAuthenticationManager : ClaimsAuthenticationManager, IEycAuthenticationManager
{
    private readonly IClaimsTransformer _claimsTransformer;
    #region ctors
    public EycAuthenticationManager(IClaimsTransformer claimsTransformer)
    {
        this._claimsTransformer = claimsTransformer;
    }
    #endregion
    public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
    {
        if (incomingPrincipal != null && !incomingPrincipal.Identity.IsAuthenticated)
        {
            return base.Authenticate(resourceName, incomingPrincipal);
        }
        return this._claimsTransformer.TransformIdentity(incomingPrincipal);
    }
}

public class ClaimsTransformer : IClaimsTransformer
{
    public ClaimsPrincipal TransformIdentity(IPrincipal principal)
    {
        if (!(principal is ClaimsPrincipal))
        {
            throw new Exception("The provided IPrincipal object is not of type ClaimsPrincipal.");
        }
        var user = (ClaimsPrincipal)principal;
        var claims = user.Claims.ToList();
        if (claims.All(x => x.Type != ClaimTypes.Email))
        {
            var upnClaim = claims.FirstOrDefault(x => x.Type == ClaimTypes.Upn);
            if (upnClaim != null)
            {
                claims.Add(new Claim(ClaimTypes.Email, upnClaim.Value));
            }
        }
        return new ClaimsPrincipal(new ClaimsIdentity(claims, principal.Identity.AuthenticationType));
    }
}

如何在asp.net Core 1.0.0中获得IOwinContext

这是如何使用Owin上下文登录的方法,应用程序是"IAppBuilder":

        app.Map("/signout", map =>
        {
            map.Run(ctx =>
            {
                ctx.Authentication.SignOut();
                return Task.CompletedTask;
            });
        });

更多细节在这里:https://leastprivilege.com/2014/02/21/test-driving-the-ws-federation-authentication-middleware-for-katana/

UseWsFederationAuthentication将无法在AspNetCore MVC 1.0.0中工作。UseWsFederationAuthentication使用非标准的OWIN密钥,不支持UseOwin,所以它不能与MVC通信。