我在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));
}
}
答案 0 :(得分:1)
以下是如何使用Owin上下文进行SignOut的方式,app是“IAppBuilder”:
app.Map("/signout", map =>
{
map.Run(ctx =>
{
ctx.Authentication.SignOut();
return Task.CompletedTask;
});
});
答案 1 :(得分:0)
UseWsFederationAuthentication在AspNetCore MVC 1.0.0中不起作用。 UseWsFederationAuthentication使用了UseOwin不支持的非标准OWIN密钥,因此无法与MVC通信。