Создание нового пользователя в ADAL TokenValidated приводит к дубликатам

У меня есть мультитенантное приложение REST. Когда новый пользователь впервые пытается получить доступ к моему приложению (и при условии, что его администратор уже предоставил разрешение приложения для своего каталога), я создаю строку пользователя в своей таблице User и сохраняю его имя / адрес электронной почты и другие поля. Я выполняю это в событии TokenValidated JwtBearerEvents.

К сожалению, я заканчиваю тем, что несколько пользователей пытаются вставить строки из-за одновременного (параллельного запроса) попадания в мой веб-API. Я делаю простой запрос SQL для пользователя по ObjectId, а затем создаю при необходимости. Это не потокобезопасно. Я попытался обернуть его в транзакцию SQL, но выбор не блокирует, и я не уверен, что EF Core позволяет мне выполнять тот тип блокировки, который мне нужен, чтобы заблокировать выполнение других выборов.

Я основываю свой код на TailSpin PnP, и они также выполняют ту же логику. Я предполагаю, что их логика сайта заставляет сначала вызывать WEB API в рамках процесса входа в систему, когда новый пользователь создается, если его не существует. В моем потоке REST API сразу запускается с помощью нескольких HTTP GET, и мне просто нужно проверить токен-носитель в заголовках и позволить ADAL его кешировать.

Помимо изменения моей клиентской логики и того, чтобы первый вызов API был единым HTTP GET, как еще я могу заставить эту работу работать в мире REST? Я не могу использовать логику SESSION для блокировки других вызовов в том же сеансе. Я не уверен, как я могу выполнить блокировку на весь сервер (который работает, только если есть один сервер). Я мог бы использовать слой БД для удержания блокировки записи, но это кажется грязным. Может быть, есть лучшее место, чтобы поставить новую пользовательскую логику? Есть ли какой-то другой способ для меня, чтобы безопасно выполнить одноразовую атомарную операцию?

1 ответ

Решение

Судя по описанию, создается впечатление, что вы создали пользовательскую запись (регистрацию), когда пользователи вызывают REST API и после проверки токена.

Чтобы устранить проблему с дублирующимися записями, один из возможных способов состоит в том, чтобы отделить процесс регистрации от проверки токена с тем же примером кода TailSpin PnP. Например, мы можем настроить обработчик токена, чтобы проверить, зарегистрировались ли пользователи, и предоставить пользовательский интерфейс для регистрации пользователей.

Другой способ заключается в том, что вы можете вставлять пользователей последовательно, используя блокировку. Например, вот код для вашей справки:

private Task tokenValidated(TokenValidatedContext context)
{
    lock (obj)
    {
        //query db and insert users here
    }
    return Task.Delay(0);

}
Другие вопросы по тегам