亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

仍已登錄 MVC 站點,但無法調用 Web API

仍已登錄 MVC 站點,但無法調用 Web API

C#
狐的傳說 2022-08-20 17:21:29
我有一個 ASP.NET MVC站點,IdentityServer4主機和一個Web API。當我使用外部提供商(Facebook)登錄MVC站點時,我登錄正常。從MVC站點,我還可以正確使用Web API。但是,第二天,我仍然登錄到MVC站點,但是當我嘗試訪問Web API時,我得到一個“未經授權的例外”。因此,盡管我仍然登錄到 MVC 站點,但我不再通過身份驗證從 MVC 站點中調用 Web API。我想知道如何處理這種情況,以及如何配置IdentityServer4。為什么一天后我仍然登錄到 MVC 站點?如何配置?如果我仍然登錄到 MVC 站點,為什么我仍然無法調用 Web API?我可以同步過期時間嗎?或者我應該如何處理這個問題?MVC 應用程序的配置如下: services.AddAuthentication(options =>        {            options.DefaultScheme = "Cookies";            options.DefaultChallengeScheme = "oidc";         })        .AddCookie("Cookies")        .AddOpenIdConnect("oidc", options =>        {            options.SignInScheme = "Cookies";            options.Authority = mgpIdSvrSettings.Authority;            options.RequireHttpsMetadata = false;                            options.ClientId = mgpIdSvrSettings.ClientId;            options.ClientSecret = mgpIdSvrSettings.ClientSecret; // Should match the secret at IdentityServer            options.ResponseType = "code id_token"; // Use hybrid flow            options.SaveTokens = true;                            options.GetClaimsFromUserInfoEndpoint = true;                            options.Scope.Add("mgpApi");            options.Scope.Add("offline_access");                          });            所以它使用混合流。在 IdentityServer 中,MVC 客戶端的配置如下:new Client{     EnableLocalLogin = false,     ClientId = "mgpPortal",     ClientName = "MGP Portal Site",     AllowedGrantTypes = GrantTypes.Hybrid,     // where to redirect to after login     RedirectUris = mgpPortalSite.RedirectUris,     // where to redirect to after logout     PostLogoutRedirectUris = mgpPortalSite.PostLogoutRedirectUris,     // secret for authentication     ClientSecrets = mgpPortalSite.ClientSecrets.Select(cs => new Secret(cs.Sha256())).ToList(),
查看完整描述

1 回答

?
倚天杖

TA貢獻1828條經驗 獲得超3個贊

有兩種類型的身份驗證,cookie 和持有者。


如果 Cookie 使您保持登錄狀態,則持有者令牌無法登錄。因為持有者令牌設置為在某個時刻過期,不允許更改生存期。


訪問令牌過期后訪問資源 (api) 的唯一方法是讓用戶再次登錄或使用刷新令牌請求新的訪問令牌,而無需用戶交互。


您已經配置了它:


options.Scope.Add("offline_access");

每次登錄時,請求將至少包含一個刷新令牌。將其存放在安全的地方,并在需要時使用。默認情況下,它設置為僅一次使用。


您可以使用類似此代碼的內容來續訂令牌(因為您實際上不是在刷新它,而是在替換它)。需要包含“標識模型”NuGet 包,如標識服務器的示例所示。


private async Task<TokenResponse> RenewTokensAsync()

{

    // Initialize the token endpoint:

    var client = _httpClientFactory.CreateClient();

    var disco = await client.GetDiscoveryDocumentAsync("http://localhost:5000");


    if (disco.IsError) throw new Exception(disco.Error);


    // Read the stored refresh token:

    var rt = await HttpContext.GetTokenAsync("refresh_token");

    var tokenClient = _httpClientFactory.CreateClient();


    // Request a new access token:

    var tokenResult = await tokenClient.RequestRefreshTokenAsync(new RefreshTokenRequest

    {

        Address = disco.TokenEndpoint,


        ClientId = "mvc",

        ClientSecret = "secret",

        RefreshToken = rt

    });


    if (!tokenResult.IsError)

    {

        var old_id_token = await HttpContext.GetTokenAsync("id_token");

        var new_access_token = tokenResult.AccessToken;

        var new_refresh_token = tokenResult.RefreshToken;

        var expiresAt = DateTime.UtcNow + TimeSpan.FromSeconds(tokenResult.ExpiresIn);


        // Save the information in the cookie

        var info = await HttpContext.AuthenticateAsync("Cookies");


        info.Properties.UpdateTokenValue("refresh_token", new_refresh_token);

        info.Properties.UpdateTokenValue("access_token", new_access_token);

        info.Properties.UpdateTokenValue("expires_at", expiresAt.ToString("o", CultureInfo.InvariantCulture));


        await HttpContext.SignInAsync("Cookies", info.Principal, info.Properties);

        return tokenResult;

    }

    return null;

}

默認情況下,刷新令牌用法配置為一次性使用。請注意,當存儲新的刷新令牌失敗并且你應該丟失它時,請求新的刷新令牌的唯一方法是強制用戶再次登錄。


另請注意,刷新令牌可能會過期。


退后一步,當訪問令牌過期或即將過期時,需要使用它:


var accessToken = await HttpContext.GetTokenAsync("access_token");


var tokenHandler = new JwtSecurityTokenHandler();


var jwtSecurityToken = tokenHandler.ReadJwtToken(accessToken);


// Depending on the lifetime of the access token.

// This is just an example. An access token may be valid

// for less than one minute.

if (jwtSecurityToken.ValidTo < DateTime.UtcNow.AddMinutes(5))

{

    var responseToken = await RenewTokensAsync();

    if (responseToken == null)

    {

        throw new Exception("Error");

    }

    accessToken = responseToken.AccessToken;

}


// Proceed, accessToken contains a valid token.


查看完整回答
反對 回復 2022-08-20
  • 1 回答
  • 0 關注
  • 82 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號