.net C#并发端点请求返回相同的响应

v09wglhw  于 2023-08-30  发布在  .NET
关注(0)|答案(1)|浏览(127)

我有一个控制器端点,它根据参数登录用户。它工作得很好,但我发现,如果同时发送两个请求(大致),它会将两个用户作为发送请求的第一个用户登录。我已经成功地复制了这个bug,通过在一个普通标签和一个隐身标签上登录,并迅速按下登录按钮,所以“同时”意味着大致在同一秒内。

[Route("Auth")]
[OverrideTokenAuthorization(AllowAnonymousAccess = true)]
public IHttpActionResult Post([FromBody] CredentialModel credentials)
{
     if (loginModel == null)
     {
         return BadRequest("...");
     }

     try
     {
        // Legacy stuff
        _service = new ServiceFactory(_iocContainer).GetService(...);

        IHttpActionResult result = Authenticate(credentials);

        Logger.Debug(((OkNegotiatedContentResult<TokenModel>)result).Content.access_token);

        return result;
    }
    catch (Exception ex)
    {
        Logger.Error(ex, "...");
        return InternalServerError();
    }
}

字符串
我尝试过多种解决方案,例如使用lock封装try块中的代码,使用SemaphoreSlim,使用Mutex,但都不起作用。我有什么选择?
我的lock方法(不起作用):

private static readonly object _lockObject = new object();

...
try
{
    lock (_lockObject) 
    {
        // Legacy stuff
        _service = new ServiceFactory(_iocContainer).GetService(...);

        IHttpActionResult result = Authenticate(credentials);

        Logger.Debug(((OkNegotiatedContentResult<TokenModel>)result).Content.access_token);

        return result;
    }
}
catch (Exception ex)
{
    Logger.Error(ex, "...");
    return InternalServerError();
}
...


我的SemaphoreSlim方法(不起作用):

private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);

_semaphore.Wait();
...
try
{
    // Legacy stuff
    _service = new ServiceFactory(_iocContainer).GetService(...);

    IHttpActionResult result = Authenticate(credentials);

    Logger.Debug(((OkNegotiatedContentResult<TokenModel>)result).Content.access_token);

    _semaphore.Release();

    return result;
}
catch (Exception ex)
{
    Logger.Error(ex, "...");
    return InternalServerError();
}
...


Authenticate方法从一个外部.dll文件(遗留文件)创建一个新的服务示例,然后写入数据库。
我还可以尝试什么来修复同时登录错误?

8yoxcaq7

8yoxcaq71#

从您的描述来看,它看起来更像是缓存问题而不是并发问题。
客户端可能发送了错误的凭据,或者Authenticate()方法可能以某种方式缓存了以前的凭据。
尝试记录请求,查看客户端是否发送了不同的凭据。为此使用一个操作过滤器,或者,如果您使用OWIN,则添加一个中间件,该中间件仅记录请求并调用下一个请求。
如果这不是问题所在,创建两个具有不同凭据的CredentialModel对象,并连续调用Authenticate()两次:

IHttpActionResult result1 = Authenticate(new CredentialModel() { Username = "user1" });
IHttpActionResult result2 = Authenticate(new CredentialModel() { Username = "user2" });
// Check that the results are valid.

字符串

相关问题