у меня есть приложение Blazor Serverside, где я добавляю аутентификацию. После аутентификации, проверьте, находится ли пользователь в базе данных.
Если это не так, я хочу добавить их.
AuthenticationStateProvider < /code> для добавления некоторых претензий из базы данных.
У меня было вчера, что я работал с OpenID Connectrion.
После этого я добавил DummyAuthenticationHandler и перемещал вещи вокруг. /> В моих Compenetns я поиск AuthenticationState через CascadingParameter
[CascadingParameter]
public Task? AuthState { get; set; }
Проблема заключается в том, что когда вход в систему запускается из аутентификации -handler , он перезаписывает _initialValueFactory в CascadingValuesource с новым AuthencitaionState , и Code INTECTITATERTICATERSTATERPRIDER {});
}
else
{
_services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.Authority = _options.Authentication.Authority;
options.ClientId = _options.Authentication.ClientId;
options.ClientSecret = _options.Authentication.ClientSecret;
options.ResponseType = OpenIdConnectResponseType.Code;
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
options.MapInboundClaims = false;
options.TokenValidationParameters.NameClaimType = OAuthClaim.Name;
});
}
_services.AddAuthorization();
_services.AddCascadingAuthenticationState();
_services.AddScoped();
}
< /code>
DummyAuthenticationHandler < /h3>
public class DummyAuthenticationOptions : AuthenticationSchemeOptions;
public class DummyAuthenticationHandler(
IOptionsMonitor options,
ILoggerFactory logger,
UrlEncoder encoder
) : AuthenticationHandler(options, logger, encoder),
IAuthenticationSignOutHandler
{
protected override async Task HandleAuthenticateAsync()
{
await Task.CompletedTask;
var cookie = Request.Cookies.FirstOrDefault(c => c.Key == nameof(DummyAuthenticationHandler));
if (cookie.Value is null)
{
return AuthenticateResult.NoResult();
}
var cookieValue = DecodeFromBase64(cookie.Value);
var claims = JsonSerializer.Deserialize(cookieValue);
var claimsIdentity = new ClaimsIdentity(claims!.Select(c => new Claim(c.Key, c.Value)), Scheme.Name);
var ticket = new AuthenticationTicket(new ClaimsPrincipal(claimsIdentity), Scheme.Name);
return AuthenticateResult.Success(ticket);
}
protected override Task HandleChallengeAsync(AuthenticationProperties properties)
{
List claims =
[
new(OAuthClaim.SubjectId, "__404_user_not_found__"),
new(OAuthClaim.Name, "Middle McMiddleware"),
new(OAuthClaim.Email, "git@gud.commit"),
new(OAuthClaim.JsonTokenIdentifier, "GUID_NOT_FOUND_EXCEPTION"),
new(OAuthClaim.AuthenticationMethodsReferences, "pwd"),
new(OAuthClaim.IdentityProvider, "'; DROP TABLE users; '"),
new(OAuthClaim.PreferredUsername, "git@gud.commit"),
new(OAuthClaim.AuthTime, DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString()),
new(OAuthClaim.GivenName, "Middle"),
new(OAuthClaim.FamilyName, "McMiddleware"),
];
var base64Claims = EncodeToBase64(JsonSerializer.Serialize(claims));
Response.Cookies.Append(
nameof(DummyAuthenticationHandler),
base64Claims,
new CookieOptions
{
HttpOnly = true,
Secure = true,
SameSite = SameSiteMode.None,
Path = "/",
Expires = DateTimeOffset.UtcNow.AddDays(1)
}
);
if (properties.RedirectUri is not null)
{
Response.Redirect(properties.RedirectUri);
}
return Task.CompletedTask;
}
public Task SignOutAsync(AuthenticationProperties? properties)
{
Response.Cookies.Delete(nameof(DummyAuthenticationHandler));
if (properties?.RedirectUri is not null)
{
Response.Redirect(properties.RedirectUri);
}
return Task.CompletedTask;
}
private static string EncodeToBase64(string text)
{
var textBytes = Encoding.UTF8.GetBytes(text);
return Convert.ToBase64String(textBytes);
}
private static string DecodeFromBase64(string base64Text)
{
var textBytes = Convert.FromBase64String(base64Text);
return Encoding.UTF8.GetString(textBytes);
}
}
< /code>
CustomAuthenticationStateProvider < /h3>
public class CustomAuthenticationStateProvider(
IDbContextFactory dbFactory
) : ServerAuthenticationStateProvider
{
public override async Task GetAuthenticationStateAsync()
{
var authState = await base.GetAuthenticationStateAsync();
var claimsUser = authState.User;
// Get your custom data - in this case some roles
var dbUser = await UpsertUser(claimsUser);
// add some new identities to the Claims Principal
claimsUser.AddIdentity(new ClaimsIdentity([
new Claim("user_id", dbUser.UserId.ToString()),
]));
// return the modified principal
return new AuthenticationState(claimsUser);
}
private async Task UpsertUser(ClaimsPrincipal claimUser)
{
var subjectId = claimUser.Claims.FirstOrDefault(c => c.Type == OAuthClaim.SubjectId)?.Value;
if (string.IsNullOrEmpty(subjectId))
{
throw new ArgumentException("Subject ID is missing from claims");
}
// Get the user from the database
await using var dbContext = await dbFactory.CreateDbContextAsync();
var user = await dbContext.Users
.AsNoTracking()
.FirstOrDefaultAsync(u => u.SubjectId == subjectId);
if (user == null)
{
user = new User
{
SubjectId = subjectId,
FirstName = claimUser.FindFirstValue(OAuthClaim.GivenName) ?? "Unknown",
LastName = claimUser.FindFirstValue(OAuthClaim.FamilyName) ?? "Unknown",
Email = claimUser.FindFirstValue(OAuthClaim.Email) ?? "Unknown",
};
dbContext.Users.Add(user);
await dbContext.SaveChangesAsync();
dbContext.Entry(user).State = EntityState.Detached;
}
return user;
}
}
Подробнее здесь: https://stackoverflow.com/questions/795 ... post-login
Добавить претензии к пользователю из базы данных пост ⇐ C#
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение