【问题标题】:Storing access token from Identity Server in NET Core web application在 NET Core Web 应用程序中存储来自 Identity Server 的访问令牌
【发布时间】:2019-08-15 18:30:13
【问题描述】:

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

首先,我尝试使用单例存储访问令牌,在 otp 验证存储(在某些字典中)与电话号码相关的访问令牌作为密钥之后。但是,问题是因为应用程序是基于网络服务器的,并且在服务器上的生产中,并不强制每个用户都必须在服务器上运行他的应用程序实例,所以单例是无用的,因为我们很可能在示例 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;
        }

【问题讨论】:

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


    【解决方案1】:

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

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

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

    【讨论】:

    • 嗨,克里斯,感谢您的回复!简而言之,应用程序是一种在线商店,用户可以在其中购买优惠券并在商家的商店中消费。
    • 那么你需要cookie auth。
    • 如果我需要使用 cookie 身份验证,是否需要向用户请求启用 cookie,否则它将不起作用?因为我们不想强迫用户使用 cookie。
    • 你别无选择。身份验证需要 cookie。不幸的是,媒体和不知情和无知的政客们已经把饼干当作一些应该避免的险恶事物。 HTTP 是一种无状态协议,cookie 用于伪造状态。没有cookies,没有状态。干净利落。为了遵守 GDPR,您必须告知用户您的 cookie 使用情况,但最终,如果他们选择退出,他们将无法登录。这就是它的工作原理。
    • 我明白了。我认为有一些方法可以避免启用 cookie,但现在很明显我们应该使用它们。再次感谢克里斯,最好的问候!
    猜你喜欢
    • 2018-12-25
    • 1970-01-01
    • 2021-11-05
    • 1970-01-01
    • 2016-12-10
    • 2012-06-04
    • 2019-04-06
    • 2012-09-24
    • 2020-07-24
    相关资源
    最近更新 更多