我有一个使用表单身份验证的旧版 Asp.Net/MVC/Razor WebApp。
现在,因为有些用户有 Azure AD 帐户,所以我添加了一个特殊的 AD 登录按钮以及通常的代码以使其工作
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{...})
使用按钮登录后,我在 URL 中输入了以下内容:
https://localhost:44361/Account/Index?ReturnUrl=%2fAccount%2fSignIn
因此在我的 Web.config 中我注释掉了:
<!--<authentication mode="Forms">
<forms loginUrl="~/Account/Index" timeout="2880" cookieless="UseDeviceProfile" />
</authentication>-->
在这个阶段Azure AD 身份验证工作正常!但是这样做,我破坏了原来的表单身份验证:-(
打电话
FormsAuthentication.SetAuthCookie(email, false);
还不够:只要我调用控制器,我仍然会重定向到 Azure AD 登录页面
[System.Web.Mvc.Authorize]
另外我收到错误消息是因为
@Html.AntiForgeryToken()
<块引用>
类型声明 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier' 要么 'http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider' 不存在于提供的 ClaimsIdentity 中。启用防伪 令牌支持基于声明的身份验证,请验证 配置的声明提供程序在 它生成的 ClaimsIdentity 实例。如果配置的声明 提供者改为使用不同的声明类型作为唯一标识符, 可以通过设置静态属性来配置 AntiForgeryConfig.UniqueClaimTypeIdentifier。
有人可以告诉我如何结合两种身份验证方法吗? 谢谢!
答案 0 :(得分:0)
这是启动的答案:
public void ConfigureAuth(IAppBuilder app)
{
PublicClientId = "self";
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Index/"),
CookieSecure = CookieSecureOption.Always
});
app.UseOAuthBearerTokens(new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(new StatelessRepository(new DataAccessHelper()), PublicClientId),
RefreshTokenProvider = new AuthenticationTokenProvider
{
OnCreate = CreateRefreshToken,
OnReceive = RecieveRefreshToken
},
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromHours(1),
AllowInsecureHttp = true
});
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
Authority = authority,
RedirectUri = redirectUri,
PostLogoutRedirectUri = redirectUri,
Scope = OpenIdConnectScope.OpenIdProfile,
ResponseType = OpenIdConnectResponseType.CodeIdToken,
TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = $"https://login.microsoftonline.com/{tenant}/v2.0",
RoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role",
NameClaimType = "name",
},
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = OnAuthenticationFailed,
SecurityTokenValidated = OnAuthenticationSuccessded
}
}
);
}
在 Web.config 中
<system.web>
<authentication mode="None" />
<compilation debug="true" targetFramework="4.8" />
<httpRuntime targetFramework="4.8" />
</system.web>
<system.webServer>
<modules>
<remove name="FormsAuthentication" />
</modules>
</system.webServer>
最后在控制器中,验证用户凭据后:
List<Claim> claims = new List<Claim>
{
new Claim(ClaimTypes.Name, partnerUser.Email),
new Claim(ClaimTypes.Email, partnerUser.Email),
new Claim(ClaimTypes.NameIdentifier, partnerUser.Email)
};
ClaimsIdentity claimsIdentity = new ClaimsIdentity(claims,
DefaultAuthenticationTypes.ApplicationCookie);
Request.GetOwinContext().Authentication.SignIn(claimsIdentity);
加上一个 SignOut 方法:
public void SignOut()
{
IAuthenticationManager authenticationManager = HttpContext.GetOwinContext().Authentication;
foreach (ClaimsIdentity claimsIdentity in authenticationManager.User.Identities)
{
switch (claimsIdentity.AuthenticationType)
{
case DefaultAuthenticationTypes.ApplicationCookie:
authenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
break;
case CookieAuthenticationDefaults.AuthenticationType:
authenticationManager.SignOut(
OpenIdConnectAuthenticationDefaults.AuthenticationType,
CookieAuthenticationDefaults.AuthenticationType);
break;
}
}
Session.Abandon();
Session.RemoveAll();
}
最后,这是 Global.asax 的一些内容:
protected void Application_Start()
{
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
...
}