C# 如何在MVC客户端应用程序中使用刷新令牌更新令牌?

C# 如何在MVC客户端应用程序中使用刷新令牌更新令牌?,c#,asp.net-mvc,asp.net-web-api,oauth,C#,Asp.net Mvc,Asp.net Web Api,Oauth,我的解决方案中有两种类型的应用程序 1) Web api应用程序 2) MMC c#应用程序 在这里,我创建了具有令牌身份验证功能的WebAPI应用程序。 在此应用程序中,从SQL server数据库验证用户名和密码。 i、 e如果任何用户请求web api令牌,则该用户详细信息必须出现在数据库表中。(在用户表Id、用户名、密码列中有数据)。 所以我的web api应用程序连接到数据库服务器 现在我创建了MVC应用程序,它使用web api并访问数据。 我在这里做的是,当用户把凭证放到mvc应用

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

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

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

在这里,我得到了来自web api的JSON响应和诸如“访问令牌”、“过期令牌”、“刷新令牌”等数据 我将所有这些详细信息存储在会话对象中

因此,每当我从mvc应用程序请求Getdata()时,我都会将“访问令牌”传递给api并重新调整结果数据

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

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


当api获取超时访问令牌,mvc应用程序再次调用刷新令牌并继续数据事务时,我需要一些函数。

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

[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));
        }
并在该代码之后检查访问令牌的验证

 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;
        }
公共类CacheAuthorizeAttribute:AuthorizeAttribute
{
公共缓存属性(参数字符串[]角色)
:base()
{
Roles=string.Join(“,”角色);
}
授权时的公共覆盖无效(HttpActionContext actionContext)
{
字典应答;
if(SkipAuthorization(actionContext))
{
返回;
}
var userSessionManager=newusercachemanager();
if(userSessionManager.ReValidateSession(out响应))
{
基于授权(actionContext);
}
其他的
{
ApiResponse ApiResponse=新的ApiResponse(response.Values.FirstOrDefault());
actionContext.Response=actionContext.ControllerContext.Request.CreateResponse(Response.Keys.FirstOrDefault(),apiResponse);
}
}
/// 
///重新验证用户会话。通常在每次授权请求时调用。
///如果会话未过期,则延长其生存期并返回true。
///如果会话已过期或不存在,则返回false。
/// 
///如果会话有效,则为true
公共bool重新验证会话(输出字典错误响应)
{
errorResponse=新字典();
string authToken=this.GetCurrentBeareAuthorOrizationToken();
iTokeDetailRepository tokenDetailRepository=新的tokenDetailRepository();
iTokeDetailBL tokenDetailBl=新的tokenDetailBl(tokenDetailRepository);
CachedData CachedData=新的CachedData(tokenDetailBl);
如果(!string.IsNullOrEmpty(authToken))
{
var currentUserId=this.GetCurrentUserId();
var getUserTokens=cachedData.GetAccessTokens();
如果(!getUserTokens.ContainsKey(authToken))
{
//从数据库获取数据
cachedData.GetAccessToken(authToken);
getUserTokens=cachedData.GetAccessTokens();
}
返回CheckAccessToken(getUserTokens、authToken、OutErrorResponse);
}
其他的
{
errorResponse.Add(HttpStatusCode.go,“未找到访问令牌”);
}
返回false;
}
private bool CheckAccessToken(字典accessTokenDictionary、字符串authToken、out Dictionary errorResponse)
{
errorResponse=新字典();
var hasToken=accessTokenDictionary.ContainsKey(authToken);
如果(hasToken)
{
var getTokenValue=accessTokenDictionary[authToken];
var enCulture=新文化信息(“美国”);
日期时间标记;
var isCorrectDate=DateTime.TryParseExact(getTokenValue.Split(新字符[]{':'},2)[1],“dd-MMM-yyyy,hh:mm-tt”,enCulture,DateTimeStyles.None,out-tokenAddedDate);
如果(isCorrectDate)
{
如果(tokenAddedDate>=DateTime.UtcNow)
{
返回true;
}
其他的
{
//检查刷新令牌是否已过期
errorResponse.Add(HttpStatusCode.Unauthorized,“访问令牌已过期”);
}
}
其他的
{
errorResponse.Add(HttpStatusCode.go,“无效访问令牌”);
}
}
其他的
{
errorResponse.Add(HttpStatusCode.go,“无效访问令牌”);
}
返回false;
}

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

[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));
        }
并在该代码之后检查访问令牌的验证

 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;
        }
公共类CacheAuthorizeAttribute:AuthorizeAttribute
{
公共缓存属性(参数字符串[]角色)