gpt4 book ai didi

asp.net-web-api - web api - 即使对于后续请求,asp.net 身份 token 也会过期

转载 作者:行者123 更新时间:2023-12-04 21:38:23 27 4
gpt4 key购买 nike

我在 web api 中使用 asp.net 身份进行基于 token 的身份验证。

对于刷新 token ,我已根据以下链接实现

  • http://bitoftech.net/2014/07/16/enable-oauth-refresh-tokens-angularjs-app-using-asp-net-web-api-2-owin/

  • 我添加了以下两个类,并在启动配置中提到。

    从用户界面我通过 api 单独使用用户名和密码调用

    http://domain/token

    当我调用上面的api时,请求直接转到了方法 ValidateClientAuthentication .

    但是在这个方法中的逻辑是,我们需要发送客户端 ID 和客户端密码。

    我们如何在用户登录特定用户之前知道这两个?

    我认为工作流程应该是这样的,我们需要根据数据库检查用户名和密码,并应该生成访问 token 和刷新 token 。

    但在这里我在哪里做这个逻辑。

    示例中提到的这个系统的工作流程是什么?

    在这个系统之前,我会在我的应用程序中调用Common/login api,验证成功后,

    我将调用代码使用户登录
     var userIdentity=await user.GenerateUserIdentityAsync(UserManager);

    AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, userIdentity);

    在上面的代码之后,我将从用户身份生成访问 token 。

    我已经用以下实现尝试了很多次并且厌倦了流程。

    帮助我了解这里提到的逻辑和流程。

    SimpleAuthorizationServerProvider
    namespace AngularJSAuthentication.API.Providers
    {
    public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
    {
    public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    {

    string clientId = string.Empty;
    string clientSecret = string.Empty;
    Client client = null;

    if (!context.TryGetBasicCredentials(out clientId, out clientSecret))
    {
    context.TryGetFormCredentials(out clientId, out clientSecret);
    }

    if (context.ClientId == null)
    {
    //Remove the comments from the below line context.SetError, and invalidate context
    //if you want to force sending clientId/secrects once obtain access tokens.
    context.Validated();
    //context.SetError("invalid_clientId", "ClientId should be sent.");
    return Task.FromResult<object>(null);
    }

    using (AuthRepository _repo = new AuthRepository())
    {
    client = _repo.FindClient(context.ClientId);
    }

    if (client == null)
    {
    context.SetError("invalid_clientId", string.Format("Client '{0}' is not registered in the system.", context.ClientId));
    return Task.FromResult<object>(null);
    }

    if (client.ApplicationType == Models.ApplicationTypes.NativeConfidential)
    {
    if (string.IsNullOrWhiteSpace(clientSecret))
    {
    context.SetError("invalid_clientId", "Client secret should be sent.");
    return Task.FromResult<object>(null);
    }
    else
    {
    if (client.Secret != Helper.GetHash(clientSecret))
    {
    context.SetError("invalid_clientId", "Client secret is invalid.");
    return Task.FromResult<object>(null);
    }
    }
    }

    if (!client.Active)
    {
    context.SetError("invalid_clientId", "Client is inactive.");
    return Task.FromResult<object>(null);
    }

    context.OwinContext.Set<string>("as:clientAllowedOrigin", client.AllowedOrigin);
    context.OwinContext.Set<string>("as:clientRefreshTokenLifeTime", client.RefreshTokenLifeTime.ToString());

    context.Validated();
    return Task.FromResult<object>(null);
    }

    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {

    var allowedOrigin = context.OwinContext.Get<string>("as:clientAllowedOrigin");

    if (allowedOrigin == null) allowedOrigin = "*";

    context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });

    using (AuthRepository _repo = new AuthRepository())
    {
    IdentityUser user = await _repo.FindUser(context.UserName, context.Password);

    if (user == null)
    {
    context.SetError("invalid_grant", "The user name or password is incorrect.");
    return;
    }
    }

    var identity = new ClaimsIdentity(context.Options.AuthenticationType);
    identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
    identity.AddClaim(new Claim(ClaimTypes.Role, "user"));
    identity.AddClaim(new Claim("sub", context.UserName));

    var props = new AuthenticationProperties(new Dictionary<string, string>
    {
    {
    "as:client_id", (context.ClientId == null) ? string.Empty : context.ClientId
    },
    {
    "userName", context.UserName
    }
    });

    var ticket = new AuthenticationTicket(identity, props);
    context.Validated(ticket);

    }

    public override Task GrantRefreshToken(OAuthGrantRefreshTokenContext context)
    {
    var originalClient = context.Ticket.Properties.Dictionary["as:client_id"];
    var currentClient = context.ClientId;

    if (originalClient != currentClient)
    {
    context.SetError("invalid_clientId", "Refresh token is issued to a different clientId.");
    return Task.FromResult<object>(null);
    }

    // Change auth ticket for refresh token requests
    var newIdentity = new ClaimsIdentity(context.Ticket.Identity);

    var newClaim = newIdentity.Claims.Where(c => c.Type == "newClaim").FirstOrDefault();
    if (newClaim != null)
    {
    newIdentity.RemoveClaim(newClaim);
    }
    newIdentity.AddClaim(new Claim("newClaim", "newValue"));

    var newTicket = new AuthenticationTicket(newIdentity, context.Ticket.Properties);
    context.Validated(newTicket);

    return Task.FromResult<object>(null);
    }

    public override Task TokenEndpoint(OAuthTokenEndpointContext context)
    {
    foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
    {
    context.AdditionalResponseParameters.Add(property.Key, property.Value);
    }

    return Task.FromResult<object>(null);
    }

    }
    }

    SimpleRefreshTokenProvider
    namespace AngularJSAuthentication.API.Providers
    {
    public class SimpleRefreshTokenProvider : IAuthenticationTokenProvider
    {

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

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

    var refreshTokenId = Guid.NewGuid().ToString("n");

    using (AuthRepository _repo = new AuthRepository())
    {
    var refreshTokenLifeTime = context.OwinContext.Get<string>("as:clientRefreshTokenLifeTime");

    var token = new RefreshToken()
    {
    Id = Helper.GetHash(refreshTokenId),
    ClientId = clientid,
    Subject = context.Ticket.Identity.Name,
    IssuedUtc = DateTime.UtcNow,
    ExpiresUtc = DateTime.UtcNow.AddMinutes(Convert.ToDouble(refreshTokenLifeTime))
    };

    context.Ticket.Properties.IssuedUtc = token.IssuedUtc;
    context.Ticket.Properties.ExpiresUtc = token.ExpiresUtc;

    token.ProtectedTicket = context.SerializeTicket();

    var result = await _repo.AddRefreshToken(token);

    if (result)
    {
    context.SetToken(refreshTokenId);
    }

    }
    }

    public async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
    {

    var allowedOrigin = context.OwinContext.Get<string>("as:clientAllowedOrigin");
    context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });

    string hashedTokenId = Helper.GetHash(context.Token);

    using (AuthRepository _repo = new AuthRepository())
    {
    var refreshToken = await _repo.FindRefreshToken(hashedTokenId);

    if (refreshToken != null )
    {
    //Get protectedTicket from refreshToken class
    context.DeserializeTicket(refreshToken.ProtectedTicket);
    var result = await _repo.RemoveRefreshToken(hashedTokenId);
    }
    }
    }

    public void Create(AuthenticationTokenCreateContext context)
    {
    throw new NotImplementedException();
    }

    public void Receive(AuthenticationTokenReceiveContext context)
    {
    throw new NotImplementedException();
    }
    }
    }

    最佳答案

    如何使用刷新 token 并将它们存储在数据库中,例如以下两个示例:

  • http://bitoftech.net/2014/07/16/enable-oauth-refresh-tokens-angularjs-app-using-asp-net-web-api-2-owin/
  • http://leastprivilege.com/2013/11/15/adding-refresh-tokens-to-a-web-api-v2-authorization-server/

  • 正如第一个链接中广泛描述的,您可以创建自己的 token 提供程序实现来处理 token 刷新:
    public class SimpleRefreshTokenProvider : IAuthenticationTokenProvider
    {

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

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

    var refreshTokenId = Guid.NewGuid().ToString("n");

    using (AuthRepository _repo = new AuthRepository())
    {
    var refreshTokenLifeTime = context.OwinContext.Get<string>("as:clientRefreshTokenLifeTime");

    var token = new RefreshToken()
    {
    Id = Helper.GetHash(refreshTokenId),
    ClientId = clientid,
    Subject = context.Ticket.Identity.Name,
    IssuedUtc = DateTime.UtcNow,
    ExpiresUtc = DateTime.UtcNow.AddMinutes(Convert.ToDouble(refreshTokenLifeTime))
    };

    context.Ticket.Properties.IssuedUtc = token.IssuedUtc;
    context.Ticket.Properties.ExpiresUtc = token.ExpiresUtc;

    token.ProtectedTicket = context.SerializeTicket();

    var result = await _repo.AddRefreshToken(token);

    if (result)
    {
    context.SetToken(refreshTokenId);
    }

    }
    }
    }

    关于asp.net-web-api - web api - 即使对于后续请求,asp.net 身份 token 也会过期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32434922/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com