OWIN Store更新,插入或删除语句影响了意外的行数(0)错误

贝拉·古尔

我遇到了一个非常奇怪的问题,在托管我的Wep Api项目的Azure应用服务上几个小时后,刷新令牌“消失”了。我已经为我的密码流程实现了OAuth。我们的AccessToken会在1小时后过期,而我们的RefreshToken会在一周后过期。

对于某些背景。这是在Azure应用服务上发生的,我托管了我的Web Api,并且移动前端正在对其进行调用(有多个用户/移动设备对此应用服务进行了调用)。

这是使用/tokencall的示例初始呼叫的样子

在此处输入图片说明

grant_type是密码。通常,我拿回refresh_token场与一起access_tokentoken_typeexpires_in

在我推送到应用程序服务后的最初几个小时内工作正常,然后refresh_token消失了。我对此问题深感困惑。

这是我的CreateAsync代码:

public async Task CreateAsync(AuthenticationTokenCreateContext context)
    {
        var clientid = context.Ticket.Properties.Dictionary["as:client_id"];

        if (string.IsNullOrEmpty(clientid))
        {
            return;
        }

        string refreshTokenId = await CreateRefreshTokenId(clientid, context);

        if (refreshTokenId != null)
        {
            context.SetToken(refreshTokenId);
        }
        else
        {
            throw new Exception("refresh token could not be created");
        }
    }

    private async Task<string> CreateRefreshTokenId(string clientId, AuthenticationTokenCreateContext context)
    {
        var ticket = context.Ticket;
        var refreshTokenId = Guid.NewGuid().ToString("n");
        var refreshTokenLifeTime = ConfigurationManager.AppSettings["as:clientRefreshTokenLifeTime"];

        var token = new CreateRefreshTokenDTO
        {
            RefreshTokenId = refreshTokenId,
            ClientId = clientId,
            Subject = ticket.Identity.Name,
            IssuedUtc = DateTime.UtcNow,
            ExpiresUtc = DateTime.UtcNow.AddMinutes(Convert.ToDouble(refreshTokenLifeTime))
        };

        ticket.Properties.IssuedUtc = token.IssuedUtc;
        ticket.Properties.ExpiresUtc = token.ExpiresUtc;

        token.ProtectedTicket = context.SerializeTicket();

        var result = await createRefreshTokenManager.ManagerRequest(new CreateRefreshTokenRequest
        {
            RefreshToken = token
        });

        return result.IsError ? null : refreshTokenId;
    }

我在else语句中添加了异常,以查看是否会抛出异常,而实际上确实会抛出异常,这使我相信refreshTokenId为null。我还向日志表中添加了日志记录,但是无论出于何种原因,抛出此错误时,都应将其保存到DB表(我已经在本地进行了测试并可以正常工作),但在App服务器上却没有保存到表中。非常令人困惑...更新:请参阅以下为什么没有保存日志的更新

然后,在此之后应该发生的事情是,既然前端(在这种情况下为移动设备)具有访问令牌和刷新令牌,当访问令牌过期时,将再次调用,/token但使用grant_type = refresh_token在此处输入图片说明

更新

最终,我能够通过反复试验在本地重现该问题,并等待访问令牌到期(不确定)。但是无论如何,我都能产生这个错误:

Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=472540 for information on understanding and handling optimistic concurrency exceptions.

此错误是我无法将任何日志保存到数据库的原因。

我使用温莎城堡作为我的IoC和EF6。我的电话按此顺序:

1]尝试验证上下文。在这里,我再次await拨打LoginUserManager,我基本上可以获取并验证用户信息

// This is used for validating the context
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)

2] CreateAsync,用于从上下文创建访问和刷新令牌

public async Task CreateAsync(AuthenticationTokenCreateContext context)

Inside CreateAsync I make an await call CreateOrUpdateRefreshTokenManagerwhich either does an Update if entry exists or a Create. And ultimately make a SaveChanges(). This SaveChanges() is what causes the error If I don't call a SaveChanges() no entry is updated or created in that table. This is odd because in other parts of my code i dont call SaveChanges() at all at the end of the web request lifecycle yet an update/create/delete is made. Im assuming that EF/Windsor handles the saving for me.

My thoughts is that because this flow is different from all my other endpoints and that its handling two Async calls that somewhere in between I am disposing the DbContext and that is maybe why im seeing it failing on the second (CreateAsync) call. Not sure, just my thought here.

Anyway, sorry for the long winded post here. I wanted to post as much info as possible and am hoping that this may also help someone else facing this or similar issue.

Thanks!

UPDATE 2

I've noticed that after getting this error on /token call, any other (AllowAnonymous) calls i make work - even those that involve the DB. But the /token call in particular no longer works. My only way around this is to restart the server.

UPDATE 3 I was able to reproduce this issu ONLY on mobile testing (linked to Azure server) but cannot reproduce locally. Steps I used to reproduce:

  1. Log in with one account
  2. Logout
  3. Log in with another account
  4. Logout
  5. Log in with the first account I tried) - This FAILS
BellaGurl

Alright ya'll I was able to figure out this issue and i'll do my best to describe what was happening here.

For those of you who have followed a tutorial such as this one or any other similar one, you'll see that you basically have some repository structure set up along with maybe your own context which you inherit the base context, right?

In my case, I was handling the Dispose of the context at the end of the request by overriding the Dispose(bool disposing) method found in the ApiController class. If you're building a WebApi, you'll know what im talking about because any controllers you write inherit this. And if you've got some IoC set up with Lifetimes set to the end of a request, it'll dispose there :)

However, in this case of the /token call I noticed that we were never hitting any controllers...or at least none that utilized ApiController so i couldn't even hit that Dispose method. That meant that the context stayed "active". And in my second, third, fourth, etc calls to /token endpoint, I noticed in the watcher that the context calls were building up (meaning it was saving prior edits to the context i made from previous /token calls - they were never getting disposed! Thus making the context stale).

Unfortunately, the way around this for my situation was to wrap any context calls made within the /token request in a using statement, that way i knew after the using finished up it would dispose properly. And this seemed to work :)

因此,如果您有一个与我共享的类似的项目或与我共享的教程类似,则可能会遇到此问题。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

存储更新,插入或删除语句影响了意外的行数(0)。

存储更新,插入或删除语句影响了意外的行数(0),

EF:Store 更新、插入或删除语句影响了意外的行数 (0)

插入项返回-存储更新,插入或删除语句影响了意外的行数(0)

实体框架:“存储更新,插入或删除语句影响了意外的行数(0)。”

插入语句影响了意外的行数(0)

Owin ApplicationDbContext 没有更新

内容长度:OWIN为0

是否可以在 OWIN 中更新访问令牌

创建Owin TestServer之后如何更新HttpConfiguration

Owin IAppBuilder.Map意外处理所有请求

如何在OWIN中删除中间件?

在Owin中检测登录以更新数据库

Owin Odata Web API自助主机406错误

南希应用程序错误被OWIN吞没了吗?

OWIN令牌认证400浏览器对OPTIONS的错误请求

使用Owin时出现Access-Control-Allow-Origin错误

SignalR Owin Host 2.0.3出现401错误

Autofac 与 Owin

Owin的NullReferenceException

Windows Store应用程序中的MVC5 WebApi2(OWIN)和WebAuthenticationBroker

如何使用刷新令牌更新Owin访问令牌而不创建新的刷新令牌?

更新Nuget后无法找到程序集“ Microsoft.Owin ...”(及更多)

将OWIN从2.1更新到3.0.1会中断外部身份验证

使用OWIN OpenIdConnect的URL重写,ARR和SSO AzureAD使用错误的URL

SignalR 2.0错误:无法加载文件或程序集Microsoft.Owin.Security

在pi上使用mono承载asp.net owin网页会导致宿主错误

部署错误:无法加载文件或程序集“ Microsoft.Owin”或其依赖项之一

错误:SignalRRouteExtension.Mapconnection已过时。在Owin Startup类中使用MapSignalR