我有面向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;
}
答案 0 :(得分:0)
目前尚不清楚您在这里做什么。如果这是一个Web应用程序(即,向用户显示在Web浏览器之间导航的HTML视图),则您需要使用Cookie身份验证。 Web浏览器的用户无法通过每个请求传递Authorization
标头。 Cookie身份验证是在Web浏览器中保留身份验证的唯一方法。
如果这是一个API,则它位于 client 上,用于存储访问令牌并通过Authorization
标头将其与每个请求一起提交。
无论哪种情况,都不应在服务器端保留auth令牌。这不是服务器的责任。