如何通过自定义用户表进行认证

默认情况下,所有的用户信息都存储在 admin.sqlite 数据库中的一个表中。该表的结构是固定的,无法更改。

本节介绍如何使用自定义用户表中的数据进行用户认证。

首先,创建一个分组 认证(Authentication) ,选中它并添加一个名为 用户(Users) 的实体项,包含如下字段:

users_fields_jampy.png

我们不会在表中直接存储用户密码,而是在界面中使用该字段。实际存储的是加盐后的密码哈希值,保存在 password_hash 字段中。

我们还创建了名为 “角色(Roles)” 的 查找列表 ,并在 “角色 “(Roles)” 字段定义中使用。

我们为其添加了与 角色 表中相同的角色(id 和名称)。后续需要保持这些角色的同步。

roles_lookup_list_jampy.png

角色 中,需要设置只有负责该项的用户才能查看 用户(Users) 实体项。

我们在 查看表单对话框编辑表单对话框 的字段列表中移除了 password_hash 字段。

用户(Users) 服务端模块中,定义如下 on_apply 事件处理程序:

def on_apply(item, delta, params, connection):
    for d in delta:
        if not (d.rec_deleted() or d.rec_modified() and d.login.value == d.login.old_value):
            users = d.task.users.copy(handlers=False)
            users.set_where(login=d.login.value)
            users.open(fields=['login'])
            if users.rec_count:
                raise Exception('There is a user with this login - %s' % d.login.value)
        if d.password.value:
            d.edit();
            d.password_hash.value = delta.task.generate_password_hash(d.password.value)
            d.password.value = None
            d.post();

在该事件处理程序中,我们检查是否有相同登录名的用户,如果有则抛出异常,否则用 task 的 generate_password_hash 方法生成哈希,并将密码字段设为 None。

在客户端模块中,定义如下 on_field_get_text 事件处理程序。它会将密码显示为 “******” :

function on_field_get_text(field) {
    var item = field.owner;
    if (field.field_name === 'password') {
        if (item.id.value || field.value) {
            return '**********';
        }
    }
}

最后,在 任务(Task) 的服务端模块中定义 on_login 事件处理程序:

def on_login(task, form_data, info):
    users = task.users.copy(handlers=False)
    users.set_where(login=form_data['login'])
    users.open()
    if users.rec_count == 1:
        if task.check_password_hash(users.password_hash.value, form_data['password']):
            return {
                'user_id': users.id.value,
                'user_name': users.name.value,
                'role_id': users.role.value,
                'role_name': users.role.display_text
            }

现在需要在 用户(Users) 中添加一个有权限管理用户的管理员。之后即可在项目 参数 中启用安全模式(Safe mode)。