在NET Core Web应用程序中从Identity Server存储访问令牌

时间:2019-03-25 13:37:30

标签: c# .net asp.net-core identityserver4

我有面向API并通过Identity Server(也作为Web应用程序)进行身份验证的网络核心Web应用程序。因为应用程序是基于Web服务器的,所以我在存储来自Identity Server的访问令牌时遇到问题,该应用程序在每个请求中(在Header中)都需要使用该令牌才能与API通信。理想的流程是:用户启动应用程序并提示输入他的电话号码(以获取OTP代码并进行身份验证),当提交电话号码时,Identity Server与一些外部提供程序将OTP代码发送给用户,现在提示用户输入OTP代码。成功提交OTP代码后,Identity Server对其进行验证并将访问令牌提供给客户端。这就是问题开始的地方。

首先,我尝试使用单例存储访问令牌,该令牌在otp验证后存储(在某些词典中)与电话号码相关的访问令牌作为密钥。但是,问题在于,因为应用程序是基于Web服务器的,并且在服务器上的生产环境中,每个用户都必须在服务器上运行他的应用程序实例不是强制性的,所以单例是毫无用处的,因为例如我们有3-4个应用程序正在为20个用户运行,并且在这种情况下,多个用户使用同一单例! 然后我搜索了一下,发现最好的选择是在浏览器会话或文档cookie中存储访问令牌或该令牌的某些实际密钥。因此,现在应用程序的工作方式是:在OTP代码验证之后,用户的电话号码和访问令牌存储在Dictionary集合中(现在更多用户使用同一集合,因为单例对此无用),其中键是电话号码,访问令牌是值,然后是javascript触发并在cookie中设置用户电话号码(在每个请求中),现在在创建Bearer标头时,我只是从当前要求中读取cookie,并使用该电话号码从集合中获取访问令牌。 因此,此解决方案非常糟糕,因为获取访问令牌所需的一切(登录后)都是修改Cookie中的电话号码,如果您很幸运,并且与集合中的现有号码匹配,您将获取访问令牌并轻松访问API

下面是在每个请求中都要调用的方法,以便从集合中获取访问令牌,在otp验证之后,将带有电话号码的访问令牌放在集合中。

public async Task<string> GetAccessToken()
        {
            string phoneNumber = GetUserPhoneNumber();

            if (string.IsNullOrEmpty(phoneNumber))
                throw new ArgumentNullException(nameof(phoneNumber));

            if (_usersTokenStore == null || _usersTokenStore.Count == 0)
                throw new NotImplementedException(nameof(_usersTokenStore));

            var refSingleUser = new SingleUserTokenStore();
            bool userHaveAccessToken = _usersTokenStore.TryGetValue(phoneNumber, out refSingleUser);

            if (!userHaveAccessToken)
                throw new Exception($"User with {phoneNumber} not authorized.");

            if (refSingleUser.IsTimeToRefreshToken)
               return await RefreshAndGetAccessToken();

            return refSingleUser.AccessToken;
        }


private string GetUserPhoneNumber()
        {
            if (_httpContext == null)
                throw new ArgumentException(nameof(_httpContext));

            var phoneNumberCookie = _httpContext.HttpContext.Request.Cookies.Where(c => c.Key == "phone_number").FirstOrDefault();

            if (phoneNumberCookie.Value == null || phoneNumberCookie.Key == null)
                return null;

            return phoneNumberCookie.Value;
        }

1 个答案:

答案 0 :(得分:0)

目前尚不清楚您在这里做什么。如果这是一个Web应用程序(即,向用户显示在Web浏览器之间导航的HTML视图),则您需要使用Cookie身份验证。 Web浏览器的用户无法通过每个请求传递Authorization标头。 Cookie身份验证是在Web浏览器中保留身份验证的唯一方法。

如果这是一个API,则它位于 client 上,用于存储访问令牌并通过Authorization标头将其与每个请求一起提交。

无论哪种情况,都不应在服务器端保留auth令牌。这不是服务器的责任。