c# - AspNet Core 1.0.0中如何获取IOwinContext

标签 c# authentication owin ws-federation

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

这段代码

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

抛出:

InvalidOperationException: No authentication handler is configured to handle the scheme: 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));
    }
}

最佳答案

这里是如何使用 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/

关于c# - AspNet Core 1.0.0中如何获取IOwinContext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38110483/

相关文章:

c# - 如何在 linq 中重现 MySQL 语句

c# - 如何确定 HttpClient.PostAsJsonAsync 调用中出现 500 错误的问题是什么?

authentication - 当有人以我身份运行 Google Apps Script Web 应用程序时获取用户信息

asp.net - Application_EndRequest 的 OWIN 等价物是什么?

asp.net-mvc - OpenIdConnect 是唯一在 Azure Active Directory 中实现授权的中间件

c# - 全局不可改变的变量

c# - 如何正确地异步编写 Socket/NetworkStream?

linux - 如何要求身份验证和加密访问 Ubuntu 服务器上的文件和数据流端口?

PHP页面显示空白

javascript - HttpClient PostAsync 在 JQuery 中等效于 FormURLEncodedContent 而不是 JSON