Я новичок в IdentityServer и весь день боролся с этой проблемой.Настолько, что я почти сдаюсь.Я знаю, что этот вопрос задавался снова и снова, и я пробовал много разных решений, но ни одно из них не работает.Надеюсь, вы поможете мне в этом.1006 * После этого я создал новую базу данных IdentityServer и запустил миграцию.К тому времени у меня была структура базы данных Identity по умолчанию.
В Config.cs я изменил MVC client
на следующее:
new Client
{
ClientId = "mvc",
ClientName = "MVC Client",
AllowedGrantTypes = GrantTypes.Implicit,
ClientSecrets = { new Secret("47C2A9E1-6A76-3A19-F3C0-S37763QB36D9".Sha256()) },
RedirectUris = { "https://localhost:44307/signin-oidc" },
FrontChannelLogoutUri = "https://localhost:44307/signout-oidc",
PostLogoutRedirectUris = { "https://localhost:44307/signout-callback-oidc" },
AllowOfflineAccess = true,
AllowedScopes = { "openid", "profile", "api1", JwtClaimTypes.Role }
},
И изменил метод GetApis
на этот:
public static IEnumerable<ApiResource> GetApis()
{
return new ApiResource[]
{
new ApiResource("api1", "My API #1", new List<string>() { "role" })
};
}
Там, где, конечно, еще нет пользователей в базе данных, поэтому я добавил регистрационную форму и зарегистрировал двух фиктивных пользователей, одного с именем пользователя admin@example.com
и одного с именем пользователя subscriber@example.com
.
Чтобы назначить роли этим пользователям, я создал следующий метод в Startup.cs.
private async Task CreateUserRoles(IServiceProvider serviceProvider) {
var RoleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
var UserManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
IdentityResult adminRoleResult;
IdentityResult subscriberRoleResult;
bool adminRoleExists = await RoleManager.RoleExistsAsync("Admin");
bool subscriberRoleExists = await RoleManager.RoleExistsAsync("Subscriber");
if (!adminRoleExists) {
adminRoleResult = await RoleManager.CreateAsync(new IdentityRole("Admin"));
}
if(!subscriberRoleExists) {
subscriberRoleResult = await RoleManager.CreateAsync(new IdentityRole("Subscriber"));
}
ApplicationUser userToMakeAdmin = await UserManager.FindByNameAsync("admin@example.com");
await UserManager.AddToRoleAsync(userToMakeAdmin, "Admin");
ApplicationUser userToMakeSubscriber = await UserManager.FindByNameAsync("subscriber@example.com");
await UserManager.AddToRoleAsync(userToMakeSubscriber, "Subscriber");
}
В методе Configure
того же класса я добавил параметр IServiceProvider services
и вызвалВышеуказанный метод примерно так: CreateUserRoles(services).Wait();
.К этому времени моя база данных имела две роли:
Затем я создал новое решение (в том же проекте) и в файле Startup.cs этого решения добавил следующее в методе ConfigureServices
.
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options => {
options.SaveTokens = true;
options.ClientId = "mvc";
options.ClientSecret = "32D7A7W0-0ALN-2Q44-A1H4-A37990NN83BP";
options.RequireHttpsMetadata = false;
options.Authority = "http://localhost:5000/";
options.ClaimActions.MapJsonKey("role", "role");
});
После этого я добавил app.UseAuthentication();
в метод Configure
того же класса.
Затем я создал новую страницу со следующими операторами if.
if(User.Identity.IsAuthenticated) {
<div>Yes, user is authenticated</div>
}
if(User.IsInRole("ADMIN")) {
<div>Yes, user is admin</div>
}
Я вошел в систему с admin@example.com
, но второй оператор if возвращает False
.Я проверил все заявки, выполнив их циклическую обработку следующим образом.
@foreach (var claim in User.Claims) {
<dt>@claim.Type</dt>
<dd>@claim.Value</dd>
}
Но не было найдено ни одной заявки на роль, только sid, sub, idp, предпочитаемое_имя_пользователя и имя.
Я пытался получить роль там, чтобы второе выражение if возвращало True, но после попытки и попытки я еще не смог заставить его работать.Может кто-нибудь увидеть, что я должен сделать, чтобы сделать эту работу?Я абсолютный новичок в IdentityServer4 и изо всех сил стараюсь понять это.Любая помощь будет оценена.Заранее спасибо!
РЕДАКТИРОВАТЬ 1:
Благодаря этот вопрос и этот вопрос У меня возникло ощущение, что яЯ на правильном пути.Я сделал некоторые изменения, но я до сих пор не могу заставить его работать.Я только что попробовал следующее.
- Создал новый класс ProfileService в моем проекте IdentityServer со следующим содержимым.
public class MyProfileService : IProfileService {
public MyProfileService() { }
public Task GetProfileDataAsync(ProfileDataRequestContext context) {
var roleClaims = context.Subject.FindAll(JwtClaimTypes.Role);
List<string> list = context.RequestedClaimTypes.ToList();
context.IssuedClaims.AddRange(roleClaims);
return Task.CompletedTask;
}
public Task IsActiveAsync(IsActiveContext context) {
return Task.CompletedTask;
}
}
Далее я зарегистрировал этот класс в методе ConfigureServicesдобавив строку services.AddTransient<IProfileService, MyProfileService>();
.После этого я добавил новую новую строку в метод GetIdentityResources, который выглядит следующим образом.
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new IdentityResource[]
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResource("roles", new[] { "role" })
};
}
Я также добавил роли в свой клиент Mvc следующим образом: AllowedScopes = { "openid", "profile", "api1", "roles" }
.
* 1070Затем я переключился на другой проект и добавил следующие строки в oidc .AddOpenIdConnect.
options.ClaimActions.MapJsonKey("role", "role", "role");
options.TokenValidationParameters.RoleClaimType = "role";
Но все же я не могу заставить его работать так, как я хочу.Кто-нибудь знает, что мне не хватает?