我想添加对象级访问控制。
(用虚拟学生通知模式解释)
学生只有在学生具有相同的班级(标准)和指定为通知的科目时才能访问(编辑/查看)通知(新闻)。 有两个角色/小组 - '学生'和老师'
数据库架构:
# model db.py
auth.define_tables(username=False, signature=True)
db.define_table('class', Field('name'))
db.define_table('subject', Field('name'))
db.define_table('notice', Field('title'),
Field('class', db.class),
Field('subject', db.subject))
db.define_table('user_class', Field('user', db.auth_user),
Field('class', db.class))
db.define_table('user_subject', Field('user', db.auth_user),
Field('subject', db.subject))
-
#controller default.py
def has_ownership():
# Check if logged in user has class and subject to view/edit this notice
pass
@auth.requires_login()
@auth.requires(lambda: has_ownership())
def notice():
user_classes = db(db.user_class.auth_user == auth.user.id).select()
user_class_list = [clss['id'] for clss in user_classes]
user_subjects = db(db.user_subject.auth_user == auth.user.id).select()
user_subject_list = [subject['id'] for subject in user_subjects]
query = db.notice.class.belongs(user_class_list) & db.notice.subject.belongs(user_subject_list)
grid = SQLFORM.grid(query, user_signature=True)
return dict(grid=grid)
所有网址都经过数字签名,我也会根据用户的主题和课程在网格中显示记录。
所以我的问题是只有数字签名的网址足以限制用户访问其他记录? (通过更改网址中的ID)
或者我需要做额外的检查,就像我使用装饰器has_ownership
?
在web2py中是否还有其他替代方法可以实现对象级访问控制?我不想使用CRUD。
谢谢
答案 0 :(得分:1)
由于query
已经将网格显示的记录集限制为用户有权访问的记录集,因此网格的数字签名URL(默认情况下已启用)足以阻止访问任何网格其他记录。不仅会拒绝更改URL中的记录ID,而且如果用户试图篡改隐藏的" id"在编辑表单中的表单字段,表单提交将被拒绝。因此,无需has_ownership
检查。
顺便说一句,当所有lambda都调用一个函数并且传递给lambda的相同参数(在这种情况下,没有参数)时,不需要lambda。因此,装饰器可以简化为@auth.requires(has_ownership)
(当然,在这种情况下,你实际上并不需要装饰器)。