确保经过身份验证的用户只能更新自己的记录

Posted

技术标签:

【中文标题】确保经过身份验证的用户只能更新自己的记录【英文标题】:Ensure authenticated user can only update their own record 【发布时间】:2017-04-12 11:55:48 【问题描述】:

假设我有两个实体如下:

@Entity
public class ClassA 
    private Long id;

    public Long getId() 
        return id;
     

    public void setId(Long id) 
        this.id = id;
    

    @OneToMany
    private Set<ClassB> classBs = new HashSet<>();

@Entity
public class ClassB 
    private Long id;
    private String name;


    public Long getId() 
        return id;
    

    public void setId(Long id) 
        this.id = id;
    

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

也就是说,ClassA 包含一组 ClassB。还有一个更新 ClassA 的资源:

@RequestMapping(method = RequestMethod.PUT)
public ClassA update(@RequestBody ClassA a)
    // Update code here

然后在 DAO(使用休眠)中调用以下代码来更新数据库中的 ClassA:

@Override
public ClassA save(ClassA classA) 
    sessionFactory.getCurrentSession().saveOrUpdate(classA);
    return classA;

update 场景中,如果经过身份验证的用户将 ClassB 实例的 id 更改为属于另一个用户的 id,我们发现没有阻止用户的保护措施更新不属于他们的对象。有什么方法可以防止这种情况吗?防止这种情况发生的最佳做法是什么(即阻止他们更新其他用户 classB 详细信息)?

【问题讨论】:

【参考方案1】:

见Access Control using @PreAuthorize and @PostAuthorize:

使用@PreAuthorize 和@PostAuthorize 进行访问控制

最明显有用的注解是@PreAuthorize,它决定了一个方法是否可以实际被调用。例如(来自“联系人”示例应用程序)

@PreAuthorize("hasRole('USER')")
public void create(Contact contact);

这意味着只有具有“ROLE_USER”角色的用户才能访问。显然,使用传统配置和所需角色的简单配置属性可以轻松实现相同的目标。但是呢:

@PreAuthorize("hasPermission(#contact, 'admin')")
public void deletePermission(Contact contact, Sid recipient, Permission permission);

这里我们实际上使用方法参数作为表达式的一部分来确定当前用户是否具有给定联系人的“管理员”权限。内置的hasPermission() 表达式通过应用程序上下文链接到 Spring Security ACL 模块,我们将在下面看到。您可以按名称访问任何方法参数作为表达式变量。

【讨论】:

【参考方案2】:

这称为业务逻辑。 Hibernate 不知道id 字段是用来表示用户的。它不会阻止您将该字段设置为您想要的任何值。

调用这个的代码,也就是修改ID字段,需要注意id字段的限制,防止用户修改。你应该在你的 UI 和你的 DAO 之间有一个业务层来进行这种检查。

【讨论】:

感谢您的回答,我很欣赏您所说的。在这种情况下,我们在控制器和 DAO 之间确实有一个服务层,因此可以使用两者之间的逻辑来解决这个问题。我想这个问题更多的是问是否有可能自动让休眠(或者可能是弹簧/弹簧安全)为你做这项工作?或者,如果执行此操作的方法已知并记录在某处。

以上是关于确保经过身份验证的用户只能更新自己的记录的主要内容,如果未能解决你的问题,请参考以下文章

OpenFire:在 IQHandler 中,如何获取发送它的经过身份验证的用户?

EF Core:在影子属性中获取经过身份验证的用户名

ReactJS Firebase 在 Context API 全局状态下经过身份验证的用户集,但值只能通过空检查获得?

教程4 - 验证和权限

Laravel 仅在模型记录属于经过身份验证的用户时才检索它们

Flutter Firebase - 未能正确删除经过 Google 身份验证的用户