如果特定参数不满足要求,则限制授权或减少结果 [英] Restrict authorization or reduce result in case specific parameter arent satisfy requirements

查看:21
本文介绍了如果特定参数不满足要求,则限制授权或减少结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通过软件描述大学时我遇到了身份验证问题.

Describing University via software I faced an auth issue.

以前我只有一个 Headmaster 角色,可以做和访问任何东西.但就目前而言,我需要集成一个Teacher 角色.

Previously I had only a Headmaster role, which can do and access anything. But as for now, I need to integrate a Teacher role.

Teacher 角色应该可以选择访问某些功能,而这些功能很容易受到 Authorize 属性的限制.但在某些情况下,我想减少此角色允许访问的数据数量,例如不是全宇宙的学生,而是那些学习Teacher's Subject的人.

The Teacher role should have an option to access certain features, which could be easily restricted by Authorize attribute. But in some cases, I want to reduce the number of data allowed to access for this role, e.g. not all students of the universe, but the ones who study Teacher's Subject.

所有这些都已在 EF 中进行了描述(例如,教师-主体、主体-学生关系).但是现在我很难拒绝(返回 403)对 Teacher 不允许访问的科目或学生的请求.

All of this is already described in EF, (e.g. teacher-subject, subject-students relationships). But now I struggle to refuse (return 403) request for subject or students which are not allowed to access by Teacher.

我为我的服务考虑了规范模式的使用,所以结果数据将通过规范的过滤器减少,因为它有助于减少数据量,有时减少到无数据,但没有帮助完全拒绝请求.

I thought about a Specification pattern usage for my Services, so the resulting data will be reduced with a Specification's filter, as it helps reduce the data amount, sometimes to no-data, but didn't help to fully refuse a request.

您能否提供一个链接或架构理念来满足上述两个用例的期望?

Could you kindly provide me a link or an architectural idea to satisfy expectations for both use-cases specified above?

// entity models
class Subject {
    ...
    public Teacher Teacher { get; set; }
    public List<Students> { get; set; }
    ...
}

class Teacher {
    ...
    public List<Subject> Subjects { get; set; }
    ...
}
class Student {
    ...
    public List<Subject> StudiedSubjects {get; set; }
    ...
}

// first use-case I want to solve
public ActionResult<List<Student>> GetStudent()
{
    // previously I just did
    return Ok(_studentsService.GetStudents());

    // but as for now in case of Teacher role accessed the method I want to
    // reduce the number of returned students
}

// second use-case I want to solve
public ActionResult<Subject> GetSubjectDetails(int subjectId)
{
    // previously I just did
    return Ok(_subjectService.GetSubject(subjectId);

    // but as for now in case of Teacher role I need to check whether its
    // allowed to get the subject and return Access denied in case its not
}

推荐答案

对于您的第一种情况,因为 Action 根本没有参数,返回可被教师访问或没有学生的学生会更有意义如果没有人参加某个老师的所有科目,那么在这种情况下就不需要403.您可以从控制器或 将 HttpContextAssessor 注入 StudentService 并将其用于过滤.

For your first case, because the Action have no parameters at all, it'll make more sense to return Students that are accessible for a Teacher, or no Students at all if no one take all the subjects of certain Teacher, so 403 are not needed in this case. You could pass the User from controller or inject HttpContextAssessor to StudentService and use it for filtering.

对于您的第二种情况,如果 SubjectId 与上下文中的 Teacher 无关,则返回 403 是完美的情况.如果您不介意为每个请求从数据库中获取数据,您可以使用 要求 结合AuthorizationHandler 在基于策略的授权中通过从数据库中检索授权所需的任何数据来确定教师是否有权访问某些主题.实现它的步骤:

as for your second case, its a perfect situation to return 403 if the SubjectId is not related to the Teacher in context. If you dont mind getting data from database for each request, you can use Requirement combined AuthorizationHandler in a Policy-Based Authorization by retrieving any data you need for authorization from database thus determine if the teacher has access to certain Subject(s). Steps to achieve it:

首先在Startup.ConfigureServices中为Teachers-Subjects关系和处理程序设置策略:

First setup the policy for the Teachers-Subjects relation and the handlers in Startup.ConfigureServices :

services.AddAuthorization(options =>
{
    options.AddPolicy("TeacherSubject", policy => policy.Requirements.Add( new TeacherSubjectRequirement() ));
});
services.AddScoped<IAuthorizationHandler, TeacherSubjectHandler>();

接下来为该策略创建 AuthorizationHandler:

next create the AuthorizationHandler for that policy:

public class TeacherSubjectHandler : AuthorizationHandler<TeacherSubjectRequirement>
{
    readonly IHttpContextAccessor _contextAccessor;
    readonly UserManager<AppUser> _usermanager;
    readonly UserToTeacherService _userToTeacherService;

    public ThePolicyAuthorizationHandler(IHttpContextAccessor c, UserManager<AppUser> u, _userToTeacherService s)
    {
        _contextAccessor = c;
        _userManager = u;
        _userToTeacherService = s;
    }

    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext authHandlerContext, TeacherSubjectRequirement requirement)
    {
        var user = _userManager.GetUserAsync(_contextAccessor.HttpContext.User);
        var teacher = _userToTeacherService(user); //I assume this service will also retrieve teacher's subjects
        var subjectIds = teacher.Subjects.Select(s => s.SubjectId).ToList();

        if (context.Resource is AuthorizationFilterContext filterContext)
        {
            var subjectIdStr = filterContext.RouteData.Values["id"].ToString();
            if ( int.TryParse(subjectIdStr, out var subjectId) && subjectIds.Contains(subjectId) )
            {
                context.Succeed(requirement);
            }

        } 

    }
}

至于Requirement类,它只是一个空类:

as for the Requirement class, its just an empty class:

public class TeacherSubjectRequirement: IAuthorizationRequirement
{

}

由于我们在 AuthorizationHandler 中做了授权机制,所以我们可以把这个类留空.但它仍然需要基于策略的授权才能工作.

Since we're doing the authorization mechanism in AuthorizationHandler, we can leave this class empty. But it will still needed for the policy-based authorization to works.

然后为使策略生效,向控制器添加属性

And then for the policy to take effect, add attribute to the controller

[Authorize(Policy = "TeacherSubject")]
public ActionResult<Subject> GetSubjectDetails(int subjectId)
{
    //existing code
}

但老实说,我还没有尝试将基于策略的属性放在 Action 中.如果这不起作用,将属性放入控制器肯定会起作用.

But to be honest, I haven't tried putting policy-based attribute in an Action. If this doesn't work, putting the attribute in controller will surely works.

希望这会有所帮助.

这篇关于如果特定参数不满足要求,则限制授权或减少结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆