如何发布重命名用户角色名称的更改



我们正在对ASP进行更改。NET MVC应用程序。我们使用Owin和OAuth2来管理用户权限,但我们自己管理用户数据库对象。

我们在应用程序启动上有这些:

app.UseKentorOwinCookieSaver();
app.UseCookieAuthentication(GetCookieAuthenticationOptions(AuthenticationType))
.UseOpenIdConnectAuthentication(GetOpenIdConnectOptions(AuthenticationType));

当用户登录Roleenum:时,我们手动将Claims分配给他们

claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, user.Role.ToString()));

如果需要更多详细信息,则在末尾包含auth代码

所有这些都运行良好,但我们需要重命名一个角色。代码重命名很简单,当我在重命名角色后登录时,一切都很好。但是,如果我已经登录,当代码更改时,我的旧角色声明字符串仍在我的Auth Cookie中,并且不再被Auth代码识别。

因为我已经登录了,所以它不会把我带到登录页面——它只会向我显示"禁止"错误页面(就好像我输入了一个不应该访问的页面的链接)

由于我们的身份验证是通过检查您是否有"角色'x'或任何大于'x的角色"来工作的,因此我们在每个页面上都被禁止(因为现在用户没有任何角色,因此在每个Auth测试中都失败了,因为他们的角色没有通过所有测试

因此,用户无法注销。

作为一名开发人员,我可以擦除浏览器cookie并从头开始登录(此时它工作得很好),但普通用户(可能?)无法做到这一点。

我的第一个想法是这样做:http://www.britishdeveloper.co.uk/2010/09/force-client-refresh-browser-cache.html,允许所有用户在发布后注销并再次登录。不幸的是,由于每个页面都会失败,我没有地方将为相关用户运行的代码:(

我可以用身份验证代码破解,这样它就知道旧角色并授予声明权限,但这似乎很可怕。

另一种选择是修改授权代码,以便在用户没有任何公认角色的情况下将其注销,但出于某种原因,我也无法确定。

关于发布此类更改的正确方式,有什么建议或意见吗?

=-=-=--=-=-\=-==-=-

授权码:

private const string AuthenticationType = "FrontEnd" + CookieAuthenticationDefaults.AuthenticationType;
private const string IdTokenClaimName = "id_token";
public void Configuration(IAppBuilder app)
{
app.UseKentorOwinCookieSaver();
app.UseCookieAuthentication(GetCookieAuthenticationOptions(AuthenticationType))
.UseOpenIdConnectAuthentication(GetOpenIdConnectOptions(AuthenticationType));
}
private static CookieAuthenticationOptions GetCookieAuthenticationOptions(string authenticationType)
{
return new CookieAuthenticationOptions
{
AuthenticationType = authenticationType,
};
}
private OpenIdConnectAuthenticationOptions GetOpenIdConnectOptions(string authenticationType)
{
return new OpenIdConnectAuthenticationOptions
{
Authority = AuthenticationConstants.AuthenticationAuthority,
ClientId = AuthenticationConstants.ClientId,
RedirectUri = AuthenticationConstants.ClientRedirectUrl,
ResponseType = "id_token",
Scope = "openid profile email",
SignInAsAuthenticationType = authenticationType,
UseTokenLifetime = false,
Notifications = new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = n => Task.Run(() => AuthorizeIfUserExists(n)),
RedirectToIdentityProvider = n => Task.Run(() => SendIdTokenToLogout(n))
}
};
}
private static void SendIdTokenToLogout(RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> n)
{
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
{
var idTokenHint = n.OwinContext.Authentication.User.FindFirst(IdTokenClaimName).Value;
n.ProtocolMessage.IdTokenHint = idTokenHint;
}
}
private void AuthorizeIfUserExists(SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> authContext)
{
var identity = authContext.AuthenticationTicket.Identity;
var userIdClaim = GetUserIdClaim(identity);
var emailClaim = GetEmailClaim(identity);
var claimsIdentity = new ClaimsIdentity(
identity.AuthenticationType,
ClaimTypes.Name,
ClaimTypes.Role);
claimsIdentity.AddClaim(new Claim(IdTokenClaimName, authContext.ProtocolMessage.IdToken));
claimsIdentity.AddClaim(userIdClaim);
claimsIdentity.AddClaim(emailClaim);
using (var context = new DbDataContext())
{
var user = GetAndInitializeUserIfNecessary(context, userIdClaim.Value, emailClaim.Value);
// We add role and name claims to all successful logins that are also registered in our database.
if (user != null && !user.IsSoftDeleted)
{
claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, user.Role.ToString()));
claimsIdentity.AddClaim(new Claim(ClaimTypes.Name, String.Format("{0} {1}", user.FirstName, user.Surname)));
}
}
authContext.AuthenticationTicket = new AuthenticationTicket(
claimsIdentity,
authContext.AuthenticationTicket.Properties);
}

我可以使用身份验证代码进行破解,这样它就可以了解旧角色并授予声明权限,但这似乎很可怕。

这对我来说似乎最好。

您所做的更改破坏了具有活动会话的用户的向后兼容性。在这种情况下,实现零停机的通常方法是发布同时支持旧客户端和新客户端的代码,直到您确定没有旧客户端,然后删除旧代码。

最新更新