仍登录 MVC 站点,但无法调用 Web API

2024-03-01

我有一个 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(),

     AllowedScopes = new List<string>
     {
            IdentityServerConstants.StandardScopes.OpenId,
            IdentityServerConstants.StandardScopes.Profile,
            "mgpApi"
     },

     AllowOfflineAccess = true,                             
     RequireConsent = false,
},

最后是网络 API:

 services.AddAuthentication("Bearer")                
           .AddIdentityServerAuthentication(options =>
            {
                options.Authority = mgpIdSvrSettings.Authority;
                options.RequireHttpsMetadata = false;                    
                options.ApiName = mgpIdSvrSettings.ApiName;
                options.EnableCaching = true;
                options.CacheDuration = TimeSpan.FromMinutes(10);                    
            });

有两种类型的身份验证:cookie 和 bearer。

Cookie 可以让您保持登录状态,但不记名令牌却不能。因为不记名令牌被设置为在某个时间点过期,并且不允许您更改生命周期。

访问令牌过期后访问资源 (api) 的唯一方法是让用户再次登录或使用刷新令牌 http://docs.identityserver.io/en/latest/topics/grant_types.html#refresh-tokens,无需用户交互。

您已经配置了它:

options.Scope.Add("offline_access");

每次登录时,请求至少包含一个刷新令牌。将其存放在安全的地方并在需要时使用。默认情况下,它设置为仅使用一次。


您可以使用类似此代码的内容来更新令牌(因为您实际上并不是刷新它,而是替换它)。您需要包含“IdentityModel”NuGet 包,如 IdentityServer 中的示例所示。

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;
}

默认情况下,刷新令牌的使用是配置的 http://docs.identityserver.io/en/latest/topics/refresh_tokens.html作为一次性使用。请注意,当存储新的刷新令牌失败并且您应该丢失它时,请求新的刷新令牌的唯一方法是强制用户再次登录。

另请注意,刷新令牌可能会过期。


退一步来说,当访问令牌过期或即将过期时,您需要使用它:

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.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

仍登录 MVC 站点,但无法调用 Web API 的相关文章

  • 为什么 std::vector 可以处理类定义中的不完整类型?

    出现了以下问题 C 标准似乎说 std vector需要一个完整的类型才能工作 看https en cppreference com w cpp container vector https en cppreference com w cp
  • 非模板函数中的尾随返回类型[重复]

    这个问题在这里已经有答案了 我见过有人使用以下语法来实现函数 auto get next gt int 代替 int get next 我理解两者 并且我知道尾随返回类型语法对于使用 decltype 的模板代码很有用 就我个人而言 我会避
  • SOAP Web 服务:多台服务器,一个接口

    我有一个场景 需要任意数量的服务器来提供相同的 SOAP Web 服务 我想生成一组代理类 并能够为它们提供一个位置 以便在运行时将它们指向不同的服务器 不幸的是 看起来好像wsdl port节点 子节点wsdl service 要求对特定
  • C++中类成员函数相互调用有什么好处?

    我是 C 新手 我发现下面的编程风格对我来说很有趣 我在这里写了一个简化版本 include
  • CMake(Ninja 后端)使用 /MT 编译

    我有一个类似的问题CMake 使用 MT 而不是 MD 进行编译 https stackoverflow com questions 14172856 cmake compile with mt instead of md但有一些差异 我正
  • 如何在 C++ 中为指针“this”赋值

    在函数中 如何分配this一个新的价值 您可以分配对象this点于 this XY 但你不能分配直接值this this XY Error Expression is not assignable
  • 公交车公共交通算法

    我正在开发一个可以查找公交路线的离线 C 应用程序 我可以提取时间表 巴士 路线数据 我正在寻找适用于基本数据的最简单的解决方案 可以使用什么算法来查找从巴士站 A 到巴士站 B 的路线 是否有适用于 C Java 的开源解决方案 数据库的
  • 使用 STL 流时如何格式化我自己的对象?

    我想将我自己的对象输出到 STL 流 但具有自定义格式 我想出了这样的东西 但由于我之前从未使用过 locale 和 imbue 所以我不知道这是否有意义以及如何实现 MyFacet 和operator 所以我的问题是 这是否有意义以及如何
  • 从单应性估计 R/T

    我一直在尝试计算 2 个图像中的特征 然后将这些特征传递回CameraParams R没有运气 特征已成功计算并匹配 但是问题是将它们传递回R t 我明白你必须分解Homography为了使这一点成为可能 我已经使用如下方法完成了 http
  • Clang 5.0 上的 vsprintf 和 vsnprintf [-Wformat-nonliteral] 警告

    我有这段代码 static void err doit int errnoflag int level const char fmt va list ap int errno save unsigned long n char buf MA
  • 具有多个父项的 Qt 树模型

    我想构建一棵树 其中一个元素可以引用另一个元素 我想要构建的树是 像这样的东西 A B C D E F P this is a pointer to C D first child of C E second child of C I fo
  • 在 Visual Studio 2012 Express 中设置 C++ 调试环境

    我需要调试的应用程序需要设置环境变量 这在 Visual Studio 2012 中似乎非常复杂 我想做类似的事情 set path c foo c bar c windows c program files application set
  • g++ / gcc 是否支持 C++20 新的atomic_flag 功能?

    根据参考参数 https en cppreference com w cpp atomic atomic flag c 20 有丰富的 对我来说有用的 支持atomic flag运营 然而 目前尚不清楚 gcc 是否支持这些功能 它们在任何
  • 使用未命名命名空间而不是静态命名空间

    我可以假设在未命名命名空间中声明的对象相当于static namespace int x 1 static int x 2 FWIK 在这两种情况下 x将具有静态存储期限和内部链接 声明为的对象的所有规则也是如此static适用于未命名名称
  • 查找数组中的多个索引

    假设我有一个像这样的数组 string fruits watermelon apple apple kiwi pear banana 是否有一个内置函数可以让我查询 apple 的所有索引 例如 fruits FindAllIndex ap
  • 如何防止 Lotus Notes 用户转发或复制通过 System.Net.Mail 发送的邮件?

    我想使用 SMTP 客户端 uiing microsft net 以 C 作为编程语言发送电子邮件 但是对于通过SMTP客户端发送的电子邮件 我们是否可以添加 禁止转发 或 禁止复制 等安全功能 我不希望电子邮件的收件人转发或复制电子邮件的
  • C++ 中的析构函数

    我的 AB h 文件中有一个构造函数 class AB private int i public AB i 0 constructor AB i 0 destructor virtual void methodA unsigned int
  • 如何将模型绑定到动态创建的类 nancyfx

    首先感谢任何愿意查看我的问题的人 我对 Nancyfx 还很陌生 在尝试将 JSON 有效负载绑定到动态创建的类时遇到问题 我按照这篇文章中的代码动态创建了该类 在C 中动态创建一个类 https stackoverflow com que
  • 将同步 zip 操作转换为异步

    我们有一个现有的库 其中一些方法需要转换为异步方法 但是我不确定如何使用以下方法执行此操作 错误处理已被删除 该方法的目的是压缩文件并将其保存到磁盘 请注意 zip 类不公开任何异步方法 public static bool ZipAndS
  • Adobe Illustrator 中的折线简化如何工作?

    我正在开发一个记录笔划的应用程序 您可以使用定点设备来绘制笔划 在上图中 我绘制了一个笔划 其中包含 453 个数据点 我的目标是大幅减少数据点的数量 同时仍然保持原始笔画的形状 对于那些感兴趣的人 上图笔画的坐标可以作为GitHub 上的

随机推荐

  • 在 MongoDB 上执行聚合/集合交集

    我有一个查询 在对示例数据集执行一些聚合后 将以下示例视为中间数据 fileid 字段包含文件的 id 以及包含对相应文件进行了一些更改的用户数组的用户数组 id fileid 12 user a b c d id fileid 13 us
  • 我如何学习 ASP.NET? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 添加带动画的子视图

    任何人都可以帮我添加带有动画的子视图吗 我想添加带有像 CATransition 这样的动画的子视图 但是对于这个类 我们只有几种不同的动画类型 但我正在寻找实现它自己的动画的能力 视图的不同部分出现在不同的时间 也许存在一些例子或其他东西
  • watchOS2 通知模拟器

    我在 XCode 上的 watchOS2 模拟器中遇到了一个奇怪的错误 我使用 UILocalNotification 处理通知并修改静态通知的情节提要 但是当我检查值 Wants Sash Blur 并构建时 它会出现与 Carousel
  • 如何模拟反应路由器上下文

    我有相当简单的反应组件 链接包装器 如果路由处于活动状态 则会添加 活动 类 import React PropTypes from react import Link from react router const NavLink pro
  • C# 裁剪图像返回错误坐标

    几天来我一直在尝试使用 Selenium 和不同的裁剪方法来裁剪特定的图像 在我的代码之前有一个重要的说明 以下方法在两周前曾经有效 由于某种原因它现在返回一个坐标错误的图像 Go to site Driver Navigate GoToU
  • printf 忽略单个反斜杠 '\'

    我有这个代码 int main int argc char argv int i printf d s argc argv 1 return 0 如果我运行这段代码a out a b 我在用C shell 其输出为 a b 有什么方法可以将
  • 如何在大型机 COBOL 中“休眠”?

    我想我正在使用 Enterprise COBOL for z OS 模拟标准 C 库的 sleep 函数等功能的技术是什么 可能最简单的方法是使用语言环境可调用服务 https www ibm com docs en zos 2 4 0 t
  • 始终独立于目标执行 Ant 操作

    有没有办法在 Ant 构建文件中指定诸如 之类的操作 每次 ant 读取构建文件时都会执行该操作 无论调用的目标是什么 背景是 我希望在模板不存在时自动从模板创建 properties 文件 我知道 我可以指定一个执行此操作的目标 然后将其
  • 使用依赖项从 Swift 2.3 迁移到 Swift 3

    我正在努力将我的项目从 Swift 2 3 迁移到 Swift 3 但我通过 Cocoapods 使用的第三方框架遇到了问题 其中许多已经升级到 Swift 3 但也有一些尚未升级 当我构建项目时 出现错误 使用 Swift 2 3 编译的
  • 将图像放置在 CSS 中另一个现有的 `` 上

    我正在做一个页面 其中显示视频的缩略图 当您单击时 它会弹出一个 YouTube 视频 这个缩略图是 195x195 的简单图像 但最终客户端会按原样上传 我想通过 CSS 在视频图像上添加一个 播放图标 与 IE7 兼容 我不知道如何处理
  • 如何将本地 ORC 文件转换为 CSV?

    我的本地计算机上有一个 ORC 文件 我需要其中的任何合理格式 例如 CSV JSON YAML 如何将 ORC 转换为 CSV Download https orc apache org docs java tools html 解压文件
  • 访问类内的函数指针

    我在类中定义函数指针并尝试通过该类的实例访问它 但它显示错误 这是代码 1 include
  • 无法在 Eclipse 中将项目添加到 Tomcat 服务器

    我无法将我的项目添加到 Eclipse 中的服务器 这是为什么 我安装了所有必要的工具 Web Dev Java EE 服务器适配器和 Tomcat 本身 一切 我配置了运行时环境 将所有 Java 版本调整为 JDK 6 因为它应该在 T
  • 有效计算边界自适应邻域平均值

    我有一张图像 其值范围为 0 到 1 我喜欢做的是简单的平均 但是 更具体地说 对于图像边界处的单元格 我想计算位于图像范围内的邻域 内核部分的像素平均值 事实上 这可以归结为适应 平均公式 的分母 即总和除以的像素数 我设法做到这一点 如
  • 将风格应用于第一个孩子?

    有没有某种方法可以将样式应用于容器的第一个 或最后一个或第 n 个 子容器 任何包含子容器的容器 我正在尝试自定义选项卡项目的外观 以便第一个选项卡具有与其他选项卡不同的边框半径 这就是我现在所拥有的
  • 让 Java servlet 充当代理的代码?

    我有两个 Java Web 应用程序 它们有一个映射到特定 URL 的 servlet red war WEB INF classes com me myorg red RedServlet maps to http red example
  • 一个更好的程序来计算数字的平方根

    我是 C 编程语言的初学者 我的任务是编写一个程序来计算自然数的平方根 而不使用math h或任何其他库函数 除了stdio h 看看我们的合作伙伴int自始至终 对于非平方数 我们求 n 的平方根的下限 现在我已经编写了这个程序 但它只适
  • 带 goto 的扩展 asm(包括 gcc 文档中的示例)无法编译

    一些扩展的汇编语句使用goto限定符无法使用 GCC 10 1 0 进行编译 具体来说 int foo int count asm goto dec 0 jb l stop r count stop return count stop re
  • 仍登录 MVC 站点,但无法调用 Web API

    我有一个 ASP NET MVC 站点 IdentityServer4 主机和一个 Web API 当我使用外部提供商 Facebook 登录 MVC 站点时 我登录得很好 从 MVC 站点我还可以正确使用 Web API 然而 第二天 我