【问题标题】:How to update token using refresh token in MVC Client Application?如何在 MVC 客户端应用程序中使用刷新令牌更新令牌?
【发布时间】:2019-03-01 05:16:13
【问题描述】:

我的解决方案中有两种类型的应用程序 1)Web API 应用 2)MMC c#应用

在这里,我创建了具有令牌身份验证功能的 Web api 应用程序。 在此应用程序中,从 SQL 服务器数据库验证用户名和密码。 即,如果任何用户请求 Web api 令牌,则该用户详细信息必须存在于数据库表中。(在用户表 ID、用户名、密码列中有数据)。 所以我的 web api 应用程序连接到数据库服务器。

现在我创建了使用 web api 并访问数据的 MVC c# 应用程序。 当用户将凭据放入 mvc 应用程序登录屏幕并且该凭据转到 api 并验证它们时,我在这里做什么。 如果用户凭据正确,API 将给出数据响应。

在这里,我得到了来自 web api 的 JSON 响应和“access_token”、“Expire_time”、“refresh_token”等数据 我将所有这些细节都存储在 Session 对象中。

所以每当我从 mvc 应用程序请求 Getdata() 时,我都会将“access_token”传递给 api 并重新调整结果数据。

我将 web api 令牌超时设置为 2 分钟。(令牌在 2 分钟后被删除)

所以问题出在这里,我如何使用 refresh_token 在 web api 中维护用户登录会话。我不想让用户再次获得登录屏幕并返回该屏幕。 因为他每 2 分钟就会出现一次登录屏幕,这是不正确的解决方案。

当api获取超时access_token和mvc应用程序再次调用refresh_token并继续数据事务时,我想要一些功能。

【问题讨论】:

    标签: c# asp.net-mvc asp.net-web-api oauth


    【解决方案1】:

    每当您的访问令牌过期时,您都可以传递刷新令牌并可以像这样更新访问令牌。希望这会对你有所帮助。

    [AllowAnonymous]
            [HttpPost]
            public IHttpActionResult GetAccessToken(RefreshTokenModel getRefreshToken)
            {
                ApiResponse apiResponse = new ApiResponse();
                apiResponse.Message = "Your session has expired. Kindly login again.";
                try
                {
                    var getHashToken = GenerateHash.GetHash(getRefreshToken.RefreshToken);
                    var getRefreshTokenDetails = tokenDetailBl.GetRefreshTokenDetail(getHashToken);
                    if (getRefreshTokenDetails != null && getRefreshTokenDetails.ExpiresUtc > DateTime.UtcNow && !string.IsNullOrEmpty(getRefreshTokenDetails.ProtectedTicket))
                    {
                        if (getRefreshTokenDetails.DeviceType == getRefreshToken.DeviceType)
                        {
                            var currentTime = DateTime.UtcNow;
                            var refreshTokenLifeTime = Convert.ToDouble(ConfigurationManager.AppSettings["RefreshTokenExpireTime"]);
                            var tokenExpiration = Convert.ToDouble(ConfigurationManager.AppSettings["AccessTokenExpireTime"]);
                            ApiIdentityManager apiIdentityManager = new ApiIdentityManager();
    
                            var tokenData = JsonConvert.SerializeObject(new { Ticket = getRefreshTokenDetails.ProtectedTicket, DeviceId = getRefreshTokenDetails.DeviceId });
                            var getIdentityToken = apiIdentityManager.GetRefreshToken(tokenData);
    
                            // Delete Old Tokens
                            tokenDetailBl.DeleteAccessTokenByDevice(getRefreshTokenDetails.DeviceId);
                            var refreshToken = new RefreshToken()
                            {
                                RefreshTokenId = GenerateHash.GetHash(getIdentityToken.RefreshToken),
                                DeviceId = getRefreshTokenDetails.DeviceId,
                                DeviceType = getRefreshToken.DeviceType,
                                UserId = getRefreshTokenDetails.UserId,
                                IssuedUtc = currentTime,
                                ExpiresUtc = currentTime.AddMinutes(Convert.ToDouble(refreshTokenLifeTime)),
                                ProtectedTicket = getIdentityToken.Ticket
                            };
    
                            //Save new tokens
                            tokenDetailBl.SaveAccessToken(new TokenDetail
                            {
                                AccessToken = getIdentityToken.AccessToken,
                                CreatedOn = DateTime.UtcNow,
                                UserId = getRefreshTokenDetails.UserId,
                                DeviceId = getRefreshTokenDetails.DeviceId,
                                DeviceType = getRefreshToken.DeviceType
                            });
                            tokenDetailBl.SaveRefreshToken(refreshToken);
    
                            //Get token cache.
                            CachedData cachedData = new CachedData(tokenDetailBl);
                            var getAllToken = cachedData.GetAccessTokens();
                            cachedData.UpdateTokenCache(getIdentityToken.AccessToken, getRefreshTokenDetails.UserId + ":" + DateTime.UtcNow.AddMinutes(tokenExpiration).ToFormateDateTimeString());
    
                            var getUserDetails = userBl.GetUserDetails(getRefreshToken.UserId);
                            getUserDetails.DeviceId = getRefreshTokenDetails.DeviceId;
                            getUserDetails.DeviceType = getRefreshTokenDetails.DeviceType;
                            getUserDetails.AccessToken = getIdentityToken.AccessToken;
                            getUserDetails.TokenType = "bearer";
                            getUserDetails.ExpiresIn = getIdentityToken.ExpiresIn;
                            getUserDetails.Issued = getIdentityToken.Issued;
                            getUserDetails.Expires = DateTime.UtcNow.Add(TimeSpan.FromMinutes(tokenExpiration)).ToString("R");
                            getUserDetails.RefreshToken = getIdentityToken.RefreshToken;
    
    
    
                            //Dictionary<string, string> tokenResponse = new Dictionary<string, string>();
                            //tokenResponse.Add("access_token", getIdentityToken.AccessToken);
                            //tokenResponse.Add("token_type", "bearer");
                            //tokenResponse.Add("expires_in", getIdentityToken.ExpiresIn);
                            //tokenResponse.Add("issued", getIdentityToken.Issued);
                            //tokenResponse.Add("expires", DateTime.UtcNow.Add(TimeSpan.FromMinutes(tokenExpiration)).ToString("R"));
                            //tokenResponse.Add("refresh_token", getIdentityToken.RefreshToken);
                            return ResponseMessage(Request.CreateResponse(HttpStatusCode.OK, getUserDetails));
                        }
                        else
                        {
                            apiResponse.Message = "Your session has expired. Kindly login again.";
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.Error(ex);
                }
    
                return ResponseMessage(Request.CreateResponse(HttpStatusCode.Gone, apiResponse));
            }
    

    您可以使用 MVC 过滤器来检查您的访问令牌是否已过期。

    [CacheAuthorize]
        [HttpPost]
        public IHttpActionResult GetUserList(SearchRequest searchRequest)
    

    在该代码之后检查访问令牌的验证

     public class CacheAuthorizeAttribute : AuthorizeAttribute
            {
                public CacheAuthorizeAttribute(params string[] roles)
                    : base()
                {
                    Roles = string.Join(",", roles);
                }
    
                public override void OnAuthorization(HttpActionContext actionContext)
                {
    
                    Dictionary<HttpStatusCode, string> response;
                    if (SkipAuthorization(actionContext))
                    {
                        return;
                    }
    
                    var userSessionManager = new UserCacheManager();
                    if (userSessionManager.ReValidateSession(out response))
                    {
                        base.OnAuthorization(actionContext);
                    }
                    else
                    {
                        ApiResponse apiResponse = new ApiResponse(response.Values.FirstOrDefault());
                        actionContext.Response = actionContext.ControllerContext.Request.CreateResponse(response.Keys.FirstOrDefault(), apiResponse);
                    }
    
    
     }
    
    
    /// <summary>
            /// Re-validates the user session. Usually called at each authorization request.
            /// If the session is not expired, extends it lifetime and returns true.
            /// If the session is expired or does not exist, return false.
            /// </summary>
            /// <returns>true if the session is valid</returns>
            public bool ReValidateSession(out Dictionary<HttpStatusCode, string> errorResponse)
            {
    
                errorResponse = new Dictionary<HttpStatusCode, string>();
                string authToken = this.GetCurrentBearerAuthrorizationToken();
                 ITokenDetailRepository tokenDetailRepository = new TokenDetailRepository();
                 ITokenDetailBL tokenDetailBl = new TokenDetailBL(tokenDetailRepository);
                 CachedData cachedData = new CachedData(tokenDetailBl);
                if (!string.IsNullOrEmpty(authToken))
                {
                    var currentUserId = this.GetCurrentUserId();
                    var getUserTokens = cachedData.GetAccessTokens();
                    if (!getUserTokens.ContainsKey(authToken))
                    {
                        //Get Data from DB
                        cachedData.GetAccessToken(authToken);
                        getUserTokens = cachedData.GetAccessTokens();
                    }
                    return CheckAccessToken(getUserTokens, authToken, out errorResponse);
                }
                else
                {
                    errorResponse.Add(HttpStatusCode.Gone, "Access token not found.");
                }
                return false;
            }
    
     private bool CheckAccessToken(Dictionary<string, string> accessTokenDictionary, string authToken, out Dictionary<HttpStatusCode, string> errorResponse)
            {
                errorResponse = new Dictionary<HttpStatusCode, string>();
                var hasToken = accessTokenDictionary.ContainsKey(authToken);
    
                if (hasToken)
                {
                    var getTokenValue = accessTokenDictionary[authToken];
                    var enCulture = new CultureInfo("en-US");
                    DateTime tokenAddedDate;
                    var isCorrectDate = DateTime.TryParseExact(getTokenValue.Split(new char[] { ':' }, 2)[1], "dd-MMM-yyyy,hh:mm tt", enCulture, DateTimeStyles.None, out tokenAddedDate);
                    if (isCorrectDate)
                    {
                        if (tokenAddedDate >= DateTime.UtcNow)
                        {
                            return true;
                        }
                        else
                        {
                            //Check Refresh token expired or not
                            errorResponse.Add(HttpStatusCode.Unauthorized, "Access token expired.");
                        }
                    }
                    else
                    {
                        errorResponse.Add(HttpStatusCode.Gone, "Invalid access token.");
                    }
                }
                else
                {
                    errorResponse.Add(HttpStatusCode.Gone, "Invalid access token.");
                }
                return false;
            }
    

    【讨论】:

    • 我怎么知道我的访问令牌已过期?我知道 refresh_token 的概念,但我的问题出在 mvc c# 应用程序中。当我的令牌过期时,我收到错误“未经授权的访问”。除此之外,是否有任何功能可以了解令牌状态?我需要一些在 mvc 应用程序后台运行的代码,每个请求都完成,然后它将使用 refresh_token 请求新令牌。
    • @DhruvKorwala 您可以使用 MVC 过滤器在每个请求上验证访问令牌作为更新的答案。
    猜你喜欢
    • 2020-06-22
    • 2012-03-03
    • 2019-12-30
    • 2016-03-22
    • 2014-09-13
    • 2018-12-08
    • 2016-09-23
    • 2020-07-12
    • 2014-02-10
    相关资源
    最近更新 更多