使用Cassandra的用户账户管理(附实例)

125 阅读3分钟

这是一个非常简单的例子,演示了如何用Cassandra数据库管理用户账户。它可以帮助你采用一些公共和私人(认证)的功能。查看这个优秀的Cassandra数据建模视频教程和它相关代码。

数据库

CREATE KEYSPACE IF NOT EXISTS blog
WITH REPLICATION = {
    'class': 'NetworkTopologyStrategy',
    'datacenter1': 1
};


DROP TABLE IF EXISTS blog.user_accounts;
CREATE TABLE IF NOT EXISTS blog.user_accounts (
    id uuid,
    name text,
    email text,
    created_at timestamp,
    deleted_at timestamp,
    PRIMARY KEY (id)
);


DROP TABLE IF EXISTS blog.user_credentials;
CREATE TABLE IF NOT EXISTS blog.user_credentials (
    email text,
    password text,
    user_account_id uuid,
    deleted_at timestamp,
    PRIMARY KEY (email)
);


DROP TABLE IF EXISTS password_recovery_tokens;
CREATE TABLE IF NOT EXISTS password_reset_tokens (
    "token" text,
    email text,
    user_account_id uuid,
    PRIMARY KEY ("token")
) WITH default_time_to_live = 3600;

设计

为了实现一件事,不可避免地要运行多个查询。然而,由于设计的原因,带有条件的批处理操作不能跨越多个表,所以你必须确保手动回滚。

注册一个新用户(公开)

创建一个新的用户从user_credentials 开始,因为它执行email 的唯一性。之后,user_accounts ,使用同样的emailid ,从user_credentials 开始创建。id 的唯一性由user_accounts 执行,所以在发生冲突的情况下,user_credentials 必须回滚。id 是一个用户的全局标识符,永远不会改变。这个值可以在其他表中用来表示用户关联:

// Creates `user_credentials` unless `email` value is taken.
INSERT INTO user_credentials (email, password, user_account_id)
VALUES (?, ?, ?) IF NOT EXISTS;

// Creates `user_accounts` unless `id` value is taken.
INSERT INTO user_accounts (id, name, created_at, email)
VALUES (?, ?, ?, ?) IF NOT EXISTS;

忘记密码(公开)

你所需要知道的是发送密码恢复链接的电子邮件地址。如何构建令牌值由你决定。它可能只是一个哈希值或编码的令牌。令牌默认在1小时内过期,如在表层用default_time_to_live 定义:

// Select current data.
SELECT * FROM user_credentials WHERE email = 'current email';

// Insert new password reset token record.
INSERT INTO password_reset_tokens (token, email, user_account_id)
VALUES (?, ?, ?) IF NOT EXISTS;

重置密码(公开)

你已经有了附加在链接上的令牌。如果你的令牌是一个包含用户数据的编码值,你可以对来自数据库的数据进行解码和验证:

// Select current token.
SELECT * FROM password_reset_tokens WHERE token = ?;

// Update password.
UPDATE user_credentials SET password = ? WHERE email = 'current email' IF EXISTS;

// Delete current token.
DELETE FROM password_reset_tokens WHERE token = ?;

登录用户(公开)

// Select user and verify password.
SELECT * FROM user_credentials WHERE email = ?;

更改电子邮件地址 (私人)

你已经登录了,所以电子邮件是已知的:

// Select current data.
SELECT * FROM user_credentials WHERE email = 'current email';

// Create a new record using new and current data.
INSERT INTO user_credentials (email, password, user_account_id)
VALUES ('new email', 'current password', current uuid) IF NOT EXISTS;

// Update current email with new one.
UPDATE user_accounts SET email = 'new email' WHERE id = current uuid IF EXISTS;

// Delete redundant record.

更改密码 (私人)

你已经登录了,所以电子邮件是已知的。这种操作通常需要预先确认密码:

// Update current password with new one.
UPDATE user_credentials SET password = ? WHERE email = ? IF EXISTS;

删除账户 (私密)

你已经登录了,所以你的电子邮件是已知的。这样的操作往往需要事先确认密码。硬删除通常不是一个选项。使用软删除,将记录标记为带有时间戳的 "已删除":

// Select current data.
SELECT * FROM user_credentials WHERE email = 'current email';

// Soft delete.
UPDATE user_credentials SET deleted_at = ? WHERE email = 'current email' IF EXISTS;
UPDATE user_accounts SET deleted_at = ? WHERE id = current uuid IF EXISTS;