首页 > 解决方案 > 在 NET Core Web 应用程序中存储来自 Identity Server 的访问令牌

问题描述

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

首先,我尝试使用单例存储访问令牌,在 otp 验证存储(在某些字典中)与电话号码相关的访问令牌作为密钥之后。但是,问题是因为应用程序是基于网络服务器的,并且在服务器上的生产中,并不强制每个用户都必须在服务器上运行他的应用程序实例,所以单例是无用的,因为我们很可能在示例 3-4 中为 20 个用户运行应用程序并且在这种情况下,不止一个用户使用相同的单例!然后我用谷歌搜索,发现最好的选择是在浏览器会话或文档 cookie 中存储访问令牌或该令牌的一些实际密钥。所以现在应用程序的工作方式是在 OTP 代码验证用户的电话号码和访问令牌存储在 Dictionary 集合中之后(现在更多用户使用相同的集合,因为单例对此没有用)其中键是电话号码,访问令牌是值,然后javascript触发并在cookie中设置用户电话号码(在每个请求中),现在在创建承载标头时,我只需从当前请求中读取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;
        }

标签: c#.netasp.net-coreidentityserver4

解决方案


目前还不清楚你在这里做什么。如果这是一个 Web 应用程序(即向用户呈现 HTML 视图,他们在 Web 浏览器中导航),那么您需要使用 cookie 身份验证。Web 浏览器的用户无法Authorization在每个请求中传递标头。Cookie 身份验证是在 Web 浏览器中保持身份验证的唯一方法。

如果这是一个 API,那么它在客户端上存储访问令牌并通过标头将其与每个请求一起提交Authorization

在任何一种情况下,您都不应该在服务器端保留身份验证令牌。这不是服务器的责任。


推荐阅读