Вы можете использовать Middleware
+ Authorization Policy
для достижения этой цели:
- Определить политику, в которой пользователь может получить доступ только к своим собственным ресурсам.
- Вызвать
IAuthorizationService
в промежуточном программном обеспечении, которое проверяет политику перед переходом в промежуточное программное обеспечение StaticFiles
.
Например, вот AuthorizationHandler
, который выполняет это требование:
public class RestrictStaticFilesRequirement: AuthorizationHandler<RestrictStaticFilesRequirement>,IAuthorizationRequirement
{
public const string DefaultPolicyName = "Access-His-Own-Static-Files";
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RestrictStaticFilesRequirement requirement)
{
var user = context.User; // current User Principal
var userName = context.Resource as string; // current userName
// custom this requirement as you like
if(user != null && !string.IsNullOrEmpty(userName) && user.HasClaim(ClaimTypes.NameIdentifier, userName)) {
context.Succeed(requirement);
} else {
context.Fail();
}
return Task.CompletedTask;
}
}
Зарегистрируйте это требование как Policy
:
services.AddAuthorization(opts =>{
opts.AddPolicy(RestrictStaticFilesRequirement.DefaultPolicyName,pb => pb.AddRequirements(new RestrictStaticFilesRequirement()) );
});
Наконец, проверьте политику с помощью IAuthorizationService
и определите, разрешен ли текущий запрос:
app.UseAuthentication();
app.UseWhen( ctx => ctx.Request.Path.StartsWithSegments("/files/users"), appBuilder =>{
appBuilder.Use(async (context, next) => {
// get the userId in current Path : "/files/users/{userId}/...."
var userId = context.Request.Path.Value.Substring("/files/users/".Length)
.Split('/')
.FirstOrDefault();
if(string.IsNullOrEmpty(userId)){
await next(); // current URL is not for static files
return;
}
var auth= context.RequestServices.GetRequiredService<IAuthorizationService>();
var result = await auth.AuthorizeAsync( context.User, userId ,RestrictStaticFilesRequirement.DefaultPolicyName);
if(!result.Succeeded){
context.Response.StatusCode= 403;
return;
}
await next();
});
});
app.UseStaticFiles();
// ... other middlewares