gpt4 book ai didi

Azure B2C Net Core 开发工作流程

转载 作者:行者123 更新时间:2023-12-03 05:50:35 28 4
gpt4 key购买 nike

我已经克隆了以下存储库 active-directory-b2c-dotnetcore-webapp并将其用作新应用程序的起点。一切都按预期工作,直到我在代码更改后重新编译代码。每当我在正常开发过程中重新编译应用程序时, acquireTokenSilent 函数似乎都会返回 session 过期消息。这显然是有问题的,因为它迫使我在每次代码更改后重新向我的 azure 租户进行身份验证。也许这与配置的 .net core 缓存策略比 azure b2c 更多有关。这是startup.cs中的身份验证中间件:

public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddAzureAdB2C(options => Configuration.Bind("Authentication:AzureAdB2C", options))
.AddCookie();

// Add framework services.
services.AddMvc();

// Adds a default in-memory implementation of IDistributedCache.
services.AddDistributedMemoryCache();
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromHours(1);
options.CookieHttpOnly = true;
});


}

以及处理 token 缓存的类:

   public class MSALSessionCache
{
private static ReaderWriterLockSlim SessionLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
string UserId = string.Empty;
string CacheId = string.Empty;
HttpContext httpContext = null;

TokenCache cache = new TokenCache();



public MSALSessionCache(string userId, HttpContext httpcontext)
{
// not object, we want the SUB
UserId = userId;
CacheId = UserId + "_TokenCache";
httpContext = httpcontext;
Load();
}

public TokenCache GetMsalCacheInstance()
{
cache.SetBeforeAccess(BeforeAccessNotification);
cache.SetAfterAccess(AfterAccessNotification);
Load();
return cache;
}

public void SaveUserStateValue(string state)
{
SessionLock.EnterWriteLock();
httpContext.Session.SetString(CacheId + "_state", state);
SessionLock.ExitWriteLock();
}
public string ReadUserStateValue()
{
string state = string.Empty;
SessionLock.EnterReadLock();
state = (string)httpContext.Session.GetString(CacheId + "_state");
SessionLock.ExitReadLock();
return state;
}
public void Load()
{
SessionLock.EnterReadLock();
cache.Deserialize(httpContext.Session.Get(CacheId));
SessionLock.ExitReadLock();
}

public void Persist()
{
SessionLock.EnterWriteLock();

// Optimistically set HasStateChanged to false. We need to do it early to avoid losing changes made by a concurrent thread.
cache.HasStateChanged = false;

// Reflect changes in the persistent store
httpContext.Session.Set(CacheId, cache.Serialize());
SessionLock.ExitWriteLock();
}

// Triggered right before MSAL needs to access the cache.
// Reload the cache from the persistent store in case it changed since the last access.
void BeforeAccessNotification(TokenCacheNotificationArgs args)
{
Load();
}

// Triggered right after MSAL accessed the cache.
void AfterAccessNotification(TokenCacheNotificationArgs args)
{
// if the access operation resulted in a cache update
if (cache.HasStateChanged)
{
Persist();
}
}
}

以下代码块中调用 acquireTokenSilentAsync 后抛出 session 过期。这仅在重新编译应用程序后才会发生:

[Authorize]
public async Task<IActionResult> Api()
{
string responseString = "";
try
{
// Retrieve the token with the specified scopes
var scope = AzureAdB2COptions.ApiScopes.Split(' ');
string signedInUserID = HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;
TokenCache userTokenCache = new MSALSessionCache(signedInUserID, this.HttpContext).GetMsalCacheInstance();
ConfidentialClientApplication cca = new ConfidentialClientApplication(AzureAdB2COptions.ClientId, AzureAdB2COptions.Authority, AzureAdB2COptions.RedirectUri, new ClientCredential(AzureAdB2COptions.ClientSecret), userTokenCache, null);

AuthenticationResult result = await cca.AcquireTokenSilentAsync(scope, cca.Users.FirstOrDefault(), AzureAdB2COptions.Authority, false);

HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, AzureAdB2COptions.ApiUrl);

// Add token to the Authorization header and make the request
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
HttpResponseMessage response = await client.SendAsync(request);

// Handle the response
switch (response.StatusCode)
{
case HttpStatusCode.OK:
responseString = await response.Content.ReadAsStringAsync();
break;
case HttpStatusCode.Unauthorized:
responseString = $"Please sign in again. {response.ReasonPhrase}";
break;
default:
responseString = $"Error calling API. StatusCode=${response.StatusCode}";
break;
}
}
catch (MsalUiRequiredException ex)
{
responseString = $"Session has expired. Please sign in again. {ex.Message}";
}
catch (Exception ex)
{
responseString = $"Error calling API: {ex.Message}";
}

ViewData["Payload"] = $"{responseString}";
return View();
}

有没有办法让这个 session 在重新编译后仍然存在?

最佳答案

这与 token 缓存有关。

The sample README注释 MSALSessionCache 是 token 缓存的示例实现。此示例实现将缓存数据保留在内存中。它不会在应用程序重新启动时保留缓存数据,也不会在服务器场中共享缓存数据(除非您有粘性 session )。

参见here用于将缓存数据保存到分布式缓存的选项。

关于Azure B2C Net Core 开发工作流程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48388477/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com