【发布时间】:2021-10-09 17:46:04
【问题描述】:
我在理解和使我的应用程序与 Identity Server 4 一起工作时遇到了一些麻烦。我想使用数据库中的用户生成验证令牌。使用 TestUser 一切正常,所以我确定我错过了一些东西。
我将从我的用户模型开始,我将其命名为“ApplicationUser”:
public class ApplicationUser : IdentityUser
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string UserName { get; set; }
public string AvatarUrl { get; set; }
public byte[] PasswordHash { get; set; }
public byte[] PasswordSalt { get; set; }
}
通过这个模型类,我完成了用户注册和用户登录。
public async Task<ServiceResponse<int>> Register(ApplicationUser user, string password)
{
ServiceResponse<int> response = new ServiceResponse<int>();
if (await UserExists(user.Email))
{
response.Success = false;
response.Message = "User already exists.";
return response;
}
else
{
CreatePasswordHash(password, out byte[] passwordHash, out byte[] passwordSalt);
user.PasswordHash = passwordHash;
user.PasswordSalt = passwordSalt;
user.UserName = user.Email;
_context.ApplicationUsers.Add(user);
await _context.SaveChangesAsync();
response.Data = user.Id;
return response;
}
}
public async Task<ServiceResponse<string>> Login(string email, string password)
{
var response = new ServiceResponse<string>();
var user = await _context.ApplicationUsers.FirstOrDefaultAsync(x => x.Email.ToLower().Equals(email.ToLower()));
if (user == null)
{
response.Success = false;
response.Message = "User not found.";
}
else if (!VerifyPasswordHash(password, user.PasswordHash, user.PasswordSalt))
{
response.Success = false;
response.Message = "Wrong password.";
}
else
{
response.Data = await CreateToken(email, password);
}
return response;
}
“CreateToken”方法是我请求令牌的地方,它看起来像这样:
private async Task<string> CreateToken(string username, string password)
{
var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync("https://localhost:5001");
if (disco.IsError)
{
Console.WriteLine(disco.Error);
}
var tokenResponse = await client.RequestPasswordTokenAsync(new PasswordTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "ro.client",
ClientSecret = "SuperSecretPassword",
UserName = username,
Password = password,
Scope = "task-app"
});
if (tokenResponse.IsError)
{
Console.WriteLine(tokenResponse.Error);
}
Console.WriteLine(tokenResponse.Json);
return tokenResponse.Json.ToString();
}
ConfigureServices 的 Startup.cs 代码是这样的:
public void ConfigureServices(IServiceCollection services)
{
var connectionString = Configuration.GetConnectionString("DefaultConnection");
var migrationAssembly = typeof(Startup).Assembly.GetName().Name;
services.AddDbContext<DataContext>(options => options.UseMySQL(connectionString));
//services.AddDbContext<DataContext>(options =>
// options.UseSqlServer(connectionString, sql => sql.MigrationsAssembly(migrationAssembly)));
services.AddCors(options =>
{
options.AddDefaultPolicy(
builder =>
{
builder
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
options.AddPolicy("AllowAllHeaders",
builder =>
{
builder
.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Auth", Version = "v1" });
c.AddSecurityDefinition("oath2", new OpenApiSecurityScheme
{
Description = "Standard Authorization header using the Bearer schema. Example: \"bearer {token}\"",
In = ParameterLocation.Header,
Name = "Authorization",
Type = SecuritySchemeType.ApiKey
});
c.OperationFilter<SecurityRequirementsOperationFilter>();
});
services.AddIdentityServer()
//Configuration Store: clients and resources
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = builder => builder.UseMySQL(connectionString, opt => opt.MigrationsAssembly(migrationAssembly));
})
//Oprerationals Store: tokens, consets, codes, etc
.AddOperationalStore(options =>
{
options.ConfigureDbContext = builder => builder.UseMySQL(connectionString, opt => opt.MigrationsAssembly(migrationAssembly));
})
.AddAspNetIdentity<ApplicationUser>()
.AddDeveloperSigningCredential();
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<DataContext>()
.AddDefaultTokenProviders();
services.AddScoped<IAuthRepository, AuthRepository>();
}
最后我的 Identity Server 配置类是这样的:
public static class Config
{
public static List<TestUser> GetUsers()
{
return new List<TestUser>
{
new TestUser
{
SubjectId = "1",
Username = "test1",
Password = "123"
},
new TestUser
{
SubjectId = "2",
Username = "test2",
Password = "123"
}
};
}
public static IEnumerable<IdentityResource> IdentityResources => new[]
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResource
{
Name = "role",
UserClaims = new List<string> {"role"}
}
};
public static IEnumerable<ApiScope> ApiScopes => new[]
{
new ApiScope( "task-app" ),
};
public static IEnumerable<ApiResource> ApiResources => new[]
{
new ApiResource("task-app")
{
Scopes = new List<string> { "task-app" },
ApiSecrets = new List<Secret> {new Secret("ScopeSecret".Sha256())},
UserClaims = new List<string> { "role" }
}
};
public static IEnumerable<Client> Clients => new[]
{
new Client
{
ClientId = "ro.client",
ClientName = "Client Credentials Client",
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
ClientSecrets = {new Secret("SuperSecretPassword".Sha256())},
AllowedScopes = { "task-app" }
}
};
}
注册和登录方法对于简单用户来说很简单。我是否需要自定义实现注册和登录才能与 Identity Server 4 一起使用?
我是否遗漏了我的 Config 文件或 Startup 类中的某些内容?
非常感谢您的宝贵时间和帮助!
【问题讨论】:
标签: c# database identityserver4