在 ADAL TokenValidated 中创建新用户会导致重复
Creating a new user in ADAL TokenValidated results in duplicates
我有一个 multi-tenant REST 应用程序。当新用户首次尝试访问我的应用程序时(假设他们的管理员已经授予应用程序对其目录的权限),我在我的用户 table 中创建一个用户行并存储他们的 name/email 和其他字段。我在 JwtBearerEvents 的 TokenValidated 事件中执行此操作。
不幸的是,由于同时(并行请求)访问我的网站,我最终尝试插入多个用户行 API。我通过 ObjectId 为用户做了一个简单的 SQL 查询,然后在必要时创建。这不是线程安全的。我尝试将它包装在 SQL 事务中,但 select 没有阻塞,我不确定 EF Core 是否允许我执行我需要阻止其他 select 的那种锁定]s 从完成。
我的代码基于 TailSpin PnP,他们在这里也执行相同的逻辑。我的猜测是他们的站点逻辑强制首先调用 WEB API 作为 sign-in/login 过程的一部分,如果新用户不存在,则会创建新用户。在我的流程中,REST API 立即被多个 HTTP GET 击中,我只需要验证 headers 中的承载令牌并让 ADAL 缓存它。
除了更改我的客户端逻辑并强制对 API 的第一次调用是单个 HTTP GET 之外,我还能如何在 REST 世界中实现它?我不能使用 SESSION 逻辑来阻止同一 session 中的其他调用。我不确定如何在整个服务器上执行锁定(只有在只有一台服务器时才有效)。我可以使用 DB 层来持有写锁,但这看起来很脏。也许有一个更好的地方来放置创建新用户逻辑?有没有其他方法可以让我安全地执行一次性原子操作?
根据描述,您似乎是在用户调用 REST API 并验证令牌后创建用户记录(注册)。
要解决重复记录问题,一种可能的方法是将注册进度与令牌验证分开,就像代码示例 TailSpin PnP 一样。例如,我们可以自定义令牌处理程序来验证用户是否注册并为用户注册提供UI。
另一种方法是,你可以使用锁顺序插入用户。例如,这里是供您参考的代码:
private Task tokenValidated(TokenValidatedContext context)
{
lock (obj)
{
//query db and insert users here
}
return Task.Delay(0);
}
我有一个 multi-tenant REST 应用程序。当新用户首次尝试访问我的应用程序时(假设他们的管理员已经授予应用程序对其目录的权限),我在我的用户 table 中创建一个用户行并存储他们的 name/email 和其他字段。我在 JwtBearerEvents 的 TokenValidated 事件中执行此操作。
不幸的是,由于同时(并行请求)访问我的网站,我最终尝试插入多个用户行 API。我通过 ObjectId 为用户做了一个简单的 SQL 查询,然后在必要时创建。这不是线程安全的。我尝试将它包装在 SQL 事务中,但 select 没有阻塞,我不确定 EF Core 是否允许我执行我需要阻止其他 select 的那种锁定]s 从完成。
我的代码基于 TailSpin PnP,他们在这里也执行相同的逻辑。我的猜测是他们的站点逻辑强制首先调用 WEB API 作为 sign-in/login 过程的一部分,如果新用户不存在,则会创建新用户。在我的流程中,REST API 立即被多个 HTTP GET 击中,我只需要验证 headers 中的承载令牌并让 ADAL 缓存它。
除了更改我的客户端逻辑并强制对 API 的第一次调用是单个 HTTP GET 之外,我还能如何在 REST 世界中实现它?我不能使用 SESSION 逻辑来阻止同一 session 中的其他调用。我不确定如何在整个服务器上执行锁定(只有在只有一台服务器时才有效)。我可以使用 DB 层来持有写锁,但这看起来很脏。也许有一个更好的地方来放置创建新用户逻辑?有没有其他方法可以让我安全地执行一次性原子操作?
根据描述,您似乎是在用户调用 REST API 并验证令牌后创建用户记录(注册)。
要解决重复记录问题,一种可能的方法是将注册进度与令牌验证分开,就像代码示例 TailSpin PnP 一样。例如,我们可以自定义令牌处理程序来验证用户是否注册并为用户注册提供UI。
另一种方法是,你可以使用锁顺序插入用户。例如,这里是供您参考的代码:
private Task tokenValidated(TokenValidatedContext context)
{
lock (obj)
{
//query db and insert users here
}
return Task.Delay(0);
}