如何在AspNet Core 1.0.0中获取IOwinContext

时间:2016-06-29 21:38:37

标签: c# authentication owin ws-federation

我在AspNetCore MVC 1.0.0中使用Owin和UseWsFederationAuthentication()。应用程序。身份验证工作完美,但我不能SignOut用户。

此代码

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

抛出:

  

InvalidOperationException:没有配置身份验证处理程序来处理该方案:Cookies

HttpContext.Authentication设置为Microsoft.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));
    }
}

2 个答案:

答案 0 :(得分:1)

以下是如何使用Owin上下文进行SignOut的方式,app是“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/

答案 1 :(得分:0)

UseWsFederationAuthentication在AspNetCore MVC 1.0.0中不起作用。 UseWsFederationAuthentication使用了UseOwin不支持的非标准OWIN密钥,因此无法与MVC通信。