获取 ASP.NET MVC5 WebAPI 令牌有时会失败

2023-12-31

获取 ASP.NET MVC5 WebAPI 令牌有时会失败

Code

string GetAPITokenSync(string username, string password, string apiBaseUri)
        {
            var token = string.Empty;

            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(apiBaseUri);
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                client.Timeout = TimeSpan.FromSeconds(60);  

                //setup login data
                var formContent = new FormUrlEncodedContent(new[]
                {
                 new KeyValuePair<string, string>("grant_type", "password"),
                 new KeyValuePair<string, string>("username", username),
                 new KeyValuePair<string, string>("password", password),
                 });

                //send request               
                Task t = Task.Run(() =>
                {
                    HttpResponseMessage responseMessage = client.PostAsync("/Token", formContent).Result;
                    var responseJson = responseMessage.Content.ReadAsStringAsync().Result;
                    var jObject = JObject.Parse(responseJson);
                    token = jObject.GetValue("access_token").ToString();
                });

                t.Wait();
                t.Dispose();
                t = null;
                GC.Collect();

                return token;
            }
        }

Error

发生一个或多个错误。 ---> System.AggregateException:一个或 发生了更多错误。 ---> System.Threading.Tasks.TaskCanceledException:任务已取消。
--- 内部异常堆栈跟踪结束 --- 在 System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceled 异常)位于 系统.线程.任务.任务1.GetResultCore(Boolean waitCompletionNotification) at System.Threading.Tasks.Task1.get_Result()

WebAPI登录方式默认不变,没有变化。

[HttpPost]
[AllowAnonymous]
[Route("Login")]
public HttpResponseMessage Login(string username, string password)
    {
        try
        {
            var identityUser = UserManager.Find(username, password);

            if (identityUser != null)
            {
                var identity = new ClaimsIdentity(Startup.OAuthOptions.AuthenticationType);
                identity.AddClaim(new Claim(ClaimTypes.Name, username));

                AuthenticationTicket ticket = new AuthenticationTicket(identity, new AuthenticationProperties());
                var currentUtc = new SystemClock().UtcNow;
                ticket.Properties.IssuedUtc = currentUtc;
                ticket.Properties.ExpiresUtc = currentUtc.Add(TimeSpan.FromMinutes(1440));

                var token = Startup.OAuthOptions.AccessTokenFormat.Protect(ticket);

                var response = new HttpResponseMessage(HttpStatusCode.OK)
                {
                    Content = new ObjectContent<object>(new
                    {
                        UserName = username,
                        ExternalAccessToken = token
                    }, Configuration.Formatters.JsonFormatter)
                };

                return response;


            }
        }
        catch (Exception)
        {
        }

        return new HttpResponseMessage(HttpStatusCode.BadRequest);
    }
}

Startupclass 默认情况下不做任何更改

 public partial class Startup
    {
        public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }

        public static string PublicClientId { get; private set; }


        public void ConfigureAuth(IAppBuilder app)
        {
            // Configure the db context and user manager to use a single instance per request
            app.CreatePerOwinContext(ApplicationDbContext.Create);
            app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

            // Enable the application to use a cookie to store information for the signed in user
            // and to use a cookie to temporarily store information about a user logging in with a third party login provider
            app.UseCookieAuthentication(new CookieAuthenticationOptions());
            app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

            // Configure the application for OAuth based flow
            PublicClientId = "self";
            OAuthOptions = new OAuthAuthorizationServerOptions
            {
                TokenEndpointPath = new PathString("/Token"),
                Provider = new ApplicationOAuthProvider(PublicClientId),
                AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
                AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
                // In production mode set AllowInsecureHttp = false
                AllowInsecureHttp = true
            };

            // Enable the application to use bearer tokens to authenticate users
            app.UseOAuthBearerTokens(OAuthOptions);
        }
    }

有什么线索吗?


很难肯定地说,但是您阻止 HttpClient 调用的方式无济于事。 HttpClient 是一个仅异步的库;你可能会遇到僵局。我建议摆脱所有.Results and .Wait()s 并异步写入所有内容,使用async/await。而你的 Task.Run 没有取得任何成果,所以应该消失。

我知道这是从控制台应用程序移植过来的 Topshelf 应用程序。我对 Topshelf 不太熟悉,但我认为,就像控制台应用程序一样,您需要阻止某处否则您的应用程序将直接退出。执行此操作的位置位于最顶部 - 应用程序的入口点。

这演示了该模式,并重写了您的GetApiToken method:

// app entry point - the only place you should block
void Main()
{
    MainAsync().Wait();
}

// the "real" starting point of your app logic. do everything async from here on
async Task MainAsync()
{
    ...
    var token = await GetApiTokenAsync(username, password, apiBaseUri);
    ...
}

async Task<string> GetApiTokenAsync(string username, string password, string apiBaseUri)
{
    var token = string.Empty;

    using (var client = new HttpClient())
    {
        client.BaseAddress = new Uri(apiBaseUri);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        client.Timeout = TimeSpan.FromSeconds(60);  

        //setup login data
        var formContent = new FormUrlEncodedContent(new[]
        {
         new KeyValuePair<string, string>("grant_type", "password"),
         new KeyValuePair<string, string>("username", username),
         new KeyValuePair<string, string>("password", password),
         });

        //send request               
        HttpResponseMessage responseMessage = await client.PostAsync("/Token", formContent);
        var responseJson = await responseMessage.Content.ReadAsStringAsync();
        var jObject = JObject.Parse(responseJson);
        token = jObject.GetValue("access_token").ToString();

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

获取 ASP.NET MVC5 WebAPI 令牌有时会失败 的相关文章

随机推荐

  • 如何强制 Linq to SQL 不使用缓存?

    当我两次进行相同的查询时 第二次它不会从数据库返回新行 我猜它只是使用缓存 这是一个 Windows 窗体应用程序 我在应用程序启动时在其中创建 dataContext 如何强制 Linq to SQL 不使用缓存 这是我遇到问题的示例函数
  • 如何在页面加载时激活 JS 数据过滤器?

    我正在这个网站上工作http fireworkslove com http fireworkslove com 我制作了具有不同类别 推荐 新闻等 的导航 我想在页面打开时显示 推荐 类别 data filter recommended 现
  • Erlang - 未定义的函数

    我正在尝试执行一个非常简单的 Erlang 代码 但它不起作用 我尝试过毫无问题地执行一些 hello worlds 但不是我自己的代码 module server Exported Functions export start 0 pro
  • 将组件的首选尺寸保留在 BorderLayout 的中心

    我有一个使用 BorderLayout 的中型 UI 中心是一个选项卡式窗格 包含具有各种布局的各种面板等 我希望该边框布局中心的面板根据以下尺寸调整大小 窗口 但我不希望面板内的组件拉伸 标签 组合框 文本字段 按钮 我希望它们保持首选大
  • 什么时候可以使用 Java 中的浮点类型进行货币计算?

    我了解到我不能使用浮点类型 float double在Java中 进行金钱计算 以及当我需要精确结果时的任何其他计算 我必须使用decimal数字类型 BigDecimal在 Java 中 代替 现在我想知道当我can使用浮点类型 他们提供
  • 使用 Convert.ToDouble 时出现异常

    我正在制作一个库存程序 要求用户输入他们想要购买的不同数量的不同物品 我使用此行将项目数转换为双精度数 以便我可以计算 但出现错误 指出我有未处理的格式异常 输入字符串的格式不正确 我有什么遗漏的吗 itembatteries Conver
  • Python Pandas 使用新的 x 轴进行插值

    我想对以下结构的 Pandas 系列进行插值 X 22 88 3 047 45 75 3 215 68 63 3 328 91 50 3 423 114 38 3 516 137 25 3 578 163 40 3 676 196 08 3
  • Jquery - 模拟点击按钮不触发功能

    Ok 所以我一直在使用 firebug 以及我编写的一些扩展来在我经常使用的网站上创建快捷方式 有件事我不明白为什么它不起作用或为什么它不可能 示例代码
  • 如何删除 mouseleave 上的下一个追加?

    我的代码有问题 当我mouseenter一个元素 一个工具栏被附加到这个元素上 但是当我mouseleave从工具栏到元素 工具栏会再次附加 我怎样才能防止这种重新附加 el on mouseenter function e var too
  • Android Studio 创建密钥库错误

    我想通过 Android Studio 生成签名的 APK 这是我的第一个应用程序 所以我需要创建新的密钥库 但是 当我填写文本框并单击 确定 时 出现错误 消息如下 密钥库已导出 但显示错误让我不敢使用它 创建密钥时出现错误 选择 JAV
  • R - 箱线图中的排序

    我正在尝试制作一系列箱形图R由 2 个因素分组 我已经成功地绘制了图 但我无法将盒子按正确的方向排序 我正在使用的数据场如下所示 Nitrogen Species Treatment 2 G L 3 R M 4 G H 4 B L 2 B
  • 更改/设置 gcloud 操作系统登录用户名?

    这么简单的问题 我正在向我的计算引擎添加一个新帐户 我添加了用户和角色以及所有有趣的东西 现在我想添加 ssh 密钥 我通过运行来执行此操作gcloud compute os login ssh keys add key file 这工作正
  • 如何让 Jest 静默测试抛出的错误

    我正在编写一个测试来断言如果提供了一个 prop 而没有提供另一个 prop 则组件会抛出错误 测试本身通过了 但控制台仍然抱怨未捕获的错误并打印整个堆栈跟踪 有没有办法让 Jest 停止打印此信息 因为它会污染测试运行程序并使其看起来像是
  • 如何使 Maven Javadoc 插件适用于任何 Java 版本

    我正在使用 Maven Javadoc 插件 如下所示
  • Java 中的无效字符常量?

    这是我的代码 import java util Scanner import javax swing JOptionPane import java text DecimalFormat Medium Speed Air 1100 feet
  • 使用 TypeScript 将 JSON(来自 Sentry)转换为 HTML

    我想学习 TypeScript 我有一个由哨兵方法返回的 JSON 字典event from exception Python 我想将其格式化为带有可扩展局部变量以及前后上下文的漂亮 HTML 结果应该大致如下所示 下面是一个 json 示
  • rbind 数据框,重复的行名问题

    虽然在一个文件中允许重复的行 和列 名称matrix 他们不允许在data frame 尝试去rbind 一些具有共同行名称的数据框突出了这个问题 考虑下面的两个数据框 foo data frame a 1 3 b 5 7 rownames
  • 从 C 访问网络数据包中未对齐数据的安全、有效的方法

    我正在用 C 为 ARM9 处理器上的 Linux 编写一个程序 该程序用于访问网络数据包 其中包括一系列标记数据 例如
  • PowerShell 中的子字符串截断字符串长度

    是否可以在 PowerShell 中截断字符串 使用SubString 达到给定的最大字符数 even如果原始字符串已经存在shorter 例如 foreach str in hello good morning hi str subStr
  • 获取 ASP.NET MVC5 WebAPI 令牌有时会失败

    获取 ASP NET MVC5 WebAPI 令牌有时会失败 Code string GetAPITokenSync string username string password string apiBaseUri var token s