Restrict authorization or reduce result in case specific parameter arent satisfy requirements
通过软件描述大学我遇到身份验证问题。
以前,我只有一个
但是就目前而言,我需要集成一个
所有这些都已在EF中进行了描述(例如,教师与受试者,学科与学生之间的关系)。但是现在我努力拒绝(返回403)对
不允许访问的学科或学生的请求。
我考虑过我的服务使用规范模式的原因,因此将使用规范的过滤器来减少生成的数据,因为这有助于减少数据量(有时减少为无数据),但并不能完全拒绝请求。
能否请您提供一个链接或体系结构的想法,以满足对上面指定的两个用例的期望?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | // 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 } |
在第一种情况下,由于该操作根本没有任何参数,因此更有意义的是让教师可以访问的学生返回,或者如果没有人接受某位老师的所有科目,则根本没有学生返回,因此在这种情况下不需要403。您可以从控制器传递
对于第二种情况,
如果
首先在
1 2 3 4 5 | services.AddAuthorization(options => { options.AddPolicy("TeacherSubject", policy => policy.Requirements.Add( new TeacherSubjectRequirement() )); }); services.AddScoped<IAuthorizationHandler, TeacherSubjectHandler>(); |
接下来为该策略创建AuthorizationHandler:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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类,它只是一个空类:
1 2 3 4 | public class TeacherSubjectRequirement: IAuthorizationRequirement { } |
由于我们正在AuthorizationHandler中进行授权机制,因此可以将此类保留为空。但是,仍需要基于策略的授权才能起作用。
然后为使该策略生效,将属性添加到控制器
1 2 3 4 5 | [Authorize(Policy ="TeacherSubject")] public ActionResult<Subject> GetSubjectDetails(int subjectId) { //existing code } |
但是,老实说,我没有尝试将基于策略的属性放入Action中。如果这不起作用,则将属性放入控制器中肯定会起作用。
希望这会有所帮助。
您的情况非常实际,这使问题变得非常有趣。但是,很高兴您阅读此文档。
使用声明使教师可以访问他们必须能够访问的信息。您可以将索赔另存为。 " TeacherName-TargetInforName他们可以访问";您可以根据老师应获取的信息量来拥有尽可能多的主张。
这对学生也是一样。您可以为该讲师班级下的学生创建索赔。就像说:"" StudentName-LectureName ",然后您可以通过检查学生是否声称自己属于特定的讲师班来进行认证。