RESTful是否限制每个经过身份验证的用户角色的资源的字段可见性?

 desn 发布于 2023-02-08 09:58

我正在构建相当复杂的REST API.整个API受身份验证保护.Person系统中的任何人都应该可以访问某些资源(例如,比方说),但是我想"隐藏"特定用户角色的某些字段.

假设Person资源有以下字段:

FirstName
LastName
BirthDate
Address

我想他们都对用户可见与HRManager角色,隐藏AddressJuniorHRManager,留下FirstName+ LastName其他人.

这种RESTful方法是根据应用于登录用户的角色的规则从响应中删除字段吗? 这是最简单的实现我猜(因为我使用的是一个具有全局响应过滤器的优秀ServiceStack ),但我不确定这是否会破坏REST规则?

我到目前为止唯一想到的另一种方法是创建特定于角色的资源(比如PersonForHRManager等).但是,这将是荒谬的,因为系统应该具有角色的可见和隐藏字段的各种组合.

1 个回答
  • 我同意你的方法,响应过滤器可能是做到这一点的最佳解决方案; 并使用描述所需角色的属性简单地标记响应DTO.我还没有看到更好的方法来进行属性级权限.

    从基于角色的响应中删除属性是完全可以接受的,如果它是公共API,则只需确保记录人们在每个角色中可以期待的属性.

    AppHost中的响应过滤器:

    this.ResponseFilters.Add((req, res, dto) => {
    
        // Get the roles you are permitted to access. You will need to store these in the request Items collection
        var roles = (from r in req.Items where r.Key == "Roles" select r.Value).FirstOrDefault() as string[];
    
        // Get the type of the response dto
        var dtoType = dto.GetType();
    
        // Loop through the properties
        foreach(var property in dtoType.GetPublicProperties()){
    
            // Ignore properties that are read-only
            if(!property.CanWrite)
                continue;
    
            // Get all the role attributes on the property
            var attributes = property.GetCustomAttributes(typeof(RequireRoleAttribute), false) as RequireRoleAttribute[];
    
            // Get all the permitted roles
            var permittedRoles = new List<string>();
            foreach(var attribute in attributes)
                permittedRoles.AddRange(attribute.Roles);
    
            // Check if there are specific permitted roles assigned to this attribute
            if(permittedRoles.Count != 0)
            {
                bool permitted = false;
    
                // Check if check require role against roles we may have.
                foreach(var role in permittedRoles){
                    if(roles.Contains(role))
                    {
                        // We have a matching role
                        permitted = true;
                        break;
                    }
                }
    
                // No permission to the property
                if(!permitted) {
                    var type = property.GetType();
    
                    // Set the field to a default value.
                    property.SetValue(dto, null);
                }
            }
        }
    });
    

    属性:

    public class RequireRoleAttribute : Attribute
    {
        public string[] Roles { get; set; }
        public RequireRoleAttribute(params string[] roles) { Roles = roles; }
    }
    

    在DTO上:

    [RequireRole("Spiderman","Superman","Batman")]
    public string Address { get; set; }
    

    笔记:

    您需要将允许的角色保存到 request.Items.Add("Roles", string[])

    我没有测试过上面的代码,所以它可能不完美,但它应该非常接近.

    我希望这有帮助.

    2023-02-08 10:02 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有