Câu trả lời được chấp nhận ( https://stackoverflow.com/a/41348219/4974715 ) không thực sự duy trì hoặc phù hợp vì "CanReadResource" đang được sử dụng như một yêu cầu (nhưng về cơ bản nên là một chính sách trong thực tế, IMO). Cách tiếp cận trong câu trả lời không ổn theo cách nó được sử dụng, bởi vì nếu một phương thức hành động yêu cầu nhiều thiết lập khiếu nại khác nhau, thì với câu trả lời đó, bạn sẽ phải viết lại nhiều thứ như ...
[ClaimRequirement(MyClaimTypes.Permission, "CanReadResource")]
[ClaimRequirement(MyClaimTypes.AnotherPermision, "AnotherClaimVaue")]
//and etc. on a single action.
Vì vậy, hãy tưởng tượng bao nhiêu tiền mã hóa sẽ mất. Lý tưởng nhất là "CanReadResource" được coi là một chính sách sử dụng nhiều khiếu nại để xác định xem người dùng có thể đọc tài nguyên hay không.
Những gì tôi làm là tôi tạo các chính sách của mình như một bảng liệt kê và sau đó lặp lại và thiết lập các yêu cầu như vậy ...
services.AddAuthorization(authorizationOptions =>
{
foreach (var policyString in Enum.GetNames(typeof(Enumerations.Security.Policy)))
{
authorizationOptions.AddPolicy(
policyString,
authorizationPolicyBuilder => authorizationPolicyBuilder.Requirements.Add(new DefaultAuthorizationRequirement((Enumerations.Security.Policy)Enum.Parse(typeof(Enumerations.Security.Policy), policyWrtString), DateTime.UtcNow)));
/* Note that thisn does not stop you from
configuring policies directly against a username, claims, roles, etc. You can do the usual.
*/
}
});
Lớp DefaultAuthorizationRequloyment trông giống như ...
public class DefaultAuthorizationRequirement : IAuthorizationRequirement
{
public Enumerations.Security.Policy Policy {get; set;} //This is a mere enumeration whose code is not shown.
public DateTime DateTimeOfSetup {get; set;} //Just in case you have to know when the app started up. And you may want to log out a user if their profile was modified after this date-time, etc.
}
public class DefaultAuthorizationHandler : AuthorizationHandler<DefaultAuthorizationRequirement>
{
private IAServiceToUse _aServiceToUse;
public DefaultAuthorizationHandler(
IAServiceToUse aServiceToUse
)
{
_aServiceToUse = aServiceToUse;
}
protected async override Task HandleRequirementAsync(AuthorizationHandlerContext context, DefaultAuthorizationRequirement requirement)
{
/*Here, you can quickly check a data source or Web API or etc.
to know the latest date-time of the user's profile modification...
*/
if (_aServiceToUse.GetDateTimeOfLatestUserProfileModication > requirement.DateTimeOfSetup)
{
context.Fail(); /*Because any modifications to user information,
e.g. if the user used another browser or if by Admin modification,
the claims of the user in this session cannot be guaranteed to be reliable.
*/
return;
}
bool shouldSucceed = false; //This should first be false, because context.Succeed(...) has to only be called if the requirement specifically succeeds.
bool shouldFail = false; /*This should first be false, because context.Fail()
doesn't have to be called if there's no security breach.
*/
// You can do anything.
await doAnythingAsync();
/*You can get the user's claims...
ALSO, note that if you have a way to priorly map users or users with certain claims
to particular policies, add those policies as claims of the user for the sake of ease.
BUT policies that require dynamic code (e.g. checking for age range) would have to be
coded in the switch-case below to determine stuff.
*/
var claims = context.User.Claims;
// You can, of course, get the policy that was hit...
var policy = requirement.Policy
//You can use a switch case to determine what policy to deal with here...
switch (policy)
{
case Enumerations.Security.Policy.CanReadResource:
/*Do stuff with the claims and change the
value of shouldSucceed and/or shouldFail.
*/
break;
case Enumerations.Security.Policy.AnotherPolicy:
/*Do stuff with the claims and change the
value of shouldSucceed and/or shouldFail.
*/
break;
// Other policies too.
default:
throw new NotImplementedException();
}
/* Note that the following conditions are
so because failure and success in a requirement handler
are not mutually exclusive. They demand certainty.
*/
if (shouldFail)
{
context.Fail(); /*Check the docs on this method to
see its implications.
*/
}
if (shouldSucceed)
{
context.Succeed(requirement);
}
}
}
Lưu ý rằng mã ở trên cũng có thể cho phép ánh xạ trước của người dùng thành chính sách trong kho dữ liệu của bạn. Vì vậy, khi soạn thảo khiếu nại cho người dùng, về cơ bản, bạn truy xuất các chính sách đã được ánh xạ trước cho người dùng trực tiếp hoặc gián tiếp (ví dụ: vì người dùng có một giá trị khiếu nại nhất định và giá trị khiếu nại đó đã được xác định và ánh xạ tới chính sách, như vậy rằng nó cung cấp ánh xạ tự động cho những người dùng cũng có giá trị khiếu nại đó) và tranh thủ các chính sách như khiếu nại, như trong trình xử lý ủy quyền, bạn chỉ cần kiểm tra xem các khiếu nại của người dùng có yêu cầu hay không.Policy như một Giá trị của một yêu cầu bồi thường yêu cầu bồi thường. Đó là đối với một cách tĩnh để đáp ứng yêu cầu chính sách, ví dụ: yêu cầu "Tên" là khá tĩnh trong tự nhiên. Vì thế,
[Authorize(Policy = nameof(Enumerations.Security.Policy.ViewRecord))]
Yêu cầu động có thể là về việc kiểm tra độ tuổi, v.v. và các chính sách sử dụng các yêu cầu đó không thể được ánh xạ trước cho người dùng.
Một ví dụ về kiểm tra khiếu nại chính sách động (ví dụ: để kiểm tra xem người dùng trên 18 tuổi) đã có câu trả lời được đưa ra bởi @blowdart ( https://stackoverflow.com/a/31465227/4974715 ).
PS: Tôi đã gõ cái này trên điện thoại của tôi. Xin lỗi vì lỗi chính tả và thiếu định dạng.