- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个项目,我在其中使用 IdentityServer4 和 PolicyServer.Local。IdentityServer4 已经有一个将必要数据存储在数据库中的实现,但 PolicyServer 没有。
所以我尝试自己实现它,并取得了成功,但从我认为我正在替换大部分 PolicyServers 代码的意义上来说感觉并不好。
例如,我已经替换了所有 PolicyServers 实体类(策略、权限、角色)并添加了我自己的类,以便我可以解析列表属性,所有这些都是因为 Entity Framework 基本上无法映射列表。
我还添加了自己的 PolicyServerRuntimeClient,因为我需要将 Evaluate-Methods 调整为新的实体类。
我的第一个 Startup.cs:
services.AddDbContext<AuthorizeDbContext>(builder =>
builder.UseSqlite(csAuthorizeContext, sqlOptions =>
sqlOptions.MigrationsAssembly(migrationsAssembly)));
services.AddScoped<IAuthorizeService, AuthorizeService>()
.AddTransient<IPolicyServerRuntimeClient, CustomPolicyServerRuntimeClient>()
.AddScoped(provider => provider.GetRequiredService<IOptionsSnapshot<Policy>>().Value);
new PolicyServerBuilder(services).AddAuthorizationPermissionPolicies();
(AuthorizeService 用于从数据库中获取值)
例如,这是我的 Permission-、Roles- 和解决 m-n 关系的 PermissionRoles-classes。
public class Permission
{
[Key]
public string Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
[ForeignKey("Policy")]
public string PolicyId { get; set; }
public IList<PermissionRole> PermissionRoles { get; set; }
}
public class PermissionRole
{
[Key]
public string Id { get; set; }
[Required]
public string PermissionId { get; set; }
public Permission Permission { get; set; }
[Required]
public string RoleId { get; set; }
public Role Role { get; set; }
}
public class Role
{
[Key]
public string Id { get; set; }
[Required]
public string Name { get; set; }
public IList<PermissionRole> PermissionRoles { get; set; }
}
这将是我在 CustomPolicyServerRuntimeClient 中的评估方法:
public async Task<PolicyResult> EvaluateAsync(ClaimsPrincipal user)
{
if (user == null)
throw new ArgumentNullException(nameof(user));
var sub = user.FindFirst("sub")?.Value;
if (String.IsNullOrWhiteSpace(sub))
return null;
var roles = _auth.Roles
.ToList()
.Where(x => EvaluateRole(x, user))
.Select(x => x.Name)
.ToArray();
var permissions = _auth.Permissions
.ToList()
.Where(x => EvaluatePermission(x, roles))
.Select(x => x.Name)
.ToArray();
var result = new PolicyResult()
{
Roles = roles.Distinct(),
Permissions = permissions.Distinct()
};
return await Task.FromResult(result);
}
internal bool EvaluateRole(Role role, ClaimsPrincipal user)
{
if (user == null)
throw new ArgumentNullException(nameof(user));
var subClaim = user.FindFirst("sub")?.Value;
var subjectsOfDbRole = _auth.UserDetails
.ToList()
.Where(x => x.RoleId.Equals(role.Id))
.Select(x => x.Subject)
.ToList();
return subjectsOfDbRole.Contains(subClaim);
}
public bool EvaluatePermission(Permission permission, IEnumerable<string> roles)
{
if (roles == null)
throw new ArgumentNullException(nameof(roles));
var permissionRoles = _auth.PermissionRoles
.ToList()
.Where(y => y.PermissionId.Equals(permission.Id))
.ToList();
if (permissionRoles.Any(x => roles.Contains(x.Role.Name)))
return true;
return false;
}
这些是我为使其正常工作所做的主要更改。
在弄清楚如何正确执行此操作之前,我不想在后端做太多工作。
预期的结果是我可能只需要更换
services.Configure<Policy>(configuration);
但最终我确实更换了比预期更多的方式。
最佳答案
您不必更改 PolicyServer 中的任何内容,只需添加一个返回所需设置的新配置提供程序即可。 PolicyServer 从 .NET Core 的配置基础结构中读取其配置。它与 appsettings.json
无关。
.NET 核心 can read configuration来自任何来源 providers .这些提供者不会做任何复杂的事情,他们“只是”读取他们的实际来源并以以下形式生成键/值字符串对:
"array:entries:0"= "value0"
"array:entries:1"= "value1"
"array:entries:2"= "value2"
"array:entries:4"= "value4"
"array:entries:5"= "value5"
appsettings.json
没有特殊含义,它只是一个 JSON 文件,.NET Core 的 JSON configuration provider读取键/值设置。该文件可以任意命名。可以从字典、数据库、远程配置服务等加载相同的数据。
例如这本字典:
public static Dictionary<string, string> arrayDict = new Dictionary<string, string>
{
{"array:entries:0", "value0"},
{"array:entries:1", "value1"},
{"array:entries:2", "value2"},
{"array:entries:4", "value4"},
{"array:entries:5", "value5"}
};
提供与此 JSON 文件相同的配置数据:
{
"array" : {
"entries" : [
"value1",
"value2",
"value3",
"value4",
"value5"
]
}
}
使用字典
您可以使用 Memory configuration provider 从字典中加载 PolicyServer 的设置.在您的配置部分,:
public static readonly Dictionary<string, string> _dict =
new Dictionary<string, string>
{
{"Policy:roles:0:name", "doctor"},
{"Policy:roles:0:subjects:0", "1"},
{"Policy:roles:0:subjects:1", "2"},
{"Policy:roles:1:name", "patient"},
{"Policy:roles:1:identityRoles:0", "customer"},
};
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddInMemoryCollection(_dict);
})
.UseStartup<Startup>();
当您在服务注册代码中调用 AddPolicyServerClient(Configuration.GetSection("Policy"))
时,设置将来自该字典。
使用原始表
您可以创建自己的配置提供程序,如 Custom Configuration Provider 所示从 ID/Value
表中检索设置。您必须将完整的 key 存储在 ID
字段中,这可能有点烦人,例如:
CREATE TABLE MyPolicySettings (ID varchar(200) PRIMARY KEY,value varchar(200))
INSERT INTO TABLE MyPolicySettings (ID,Value)
VALUES
("Policy:roles:0:name", "doctor"},
("Policy:roles:0:subjects:0", "1"),
("Policy:roles:0:subjects:1", "2"),
("Policy:roles:1:name", "patient"),
("Policy:roles:1:identityRoles:0", "customer");
使用 EF
另一种选择是将您的设置存储在适当的表中,例如 Roles
、Subjects
、IdentityRoles
并使用 ORM 加载整个结构.一旦你拥有它,你将不得不重现关键结构,例如通过在迭代器中迭代对象:
public IEnumerable<KeyValuePair<string,string>> FlattenRoles(IEnumerable<MyRole> roles)
{
int iRole=0;
foreach(var role in roles)
{
var rolePart=$"Policy:roles:{i}";
var namePair=new KeyValuePair($"{rolePart}:name",role.Name);
yield return namePair;
int iSubject=0;
foreach(var subjectPair in FlattenSubjects(role.Subject))
{
yield return subjectPair
}
//Same for identity roles etc
iRole++;
}
}
public IEnumerable<KeyValuePair<string,string>> FlattenSubjects(IEnumerable<MySubject> subjects,string rolePart)
{
var pairs=subjects.Select((subject,idx)=>
new KeyValuePair($"{rolePart}:subjects:{idx}",subject.Value);
return pairs;
}
您的自定义配置提供程序可以使用它从数据库中加载强类型类,将它们展平并将它们转换为字典,例如:
public class MyPolicyConfigurationProvider: ConfigurationProvider
{
public MyPolicyConfigurationProvider(Action<DbContextOptionsBuilder> optionsAction)
{
OptionsAction = optionsAction;
}
Action<DbContextOptionsBuilder> OptionsAction { get; }
// Load config data from EF DB.
public override void Load()
{
var builder = new DbContextOptionsBuilder<MyPoliciesContext>();
OptionsAction(builder);
using (var dbContext = new MyPoliciesContext(builder.Options))
{
var keys=FlattenRoles(dbContext.Roles);
Data=new Dictionary<string,string>(keys);
}
}
}
关于c# - 在数据库中保留实体而不是 appsettings.json,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55450393/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!