如何让 JWT 在 Autorest 生成的 SDK 中工作? (ASP.NET 核心 2.0)

Posted

技术标签:

【中文标题】如何让 JWT 在 Autorest 生成的 SDK 中工作? (ASP.NET 核心 2.0)【英文标题】:How do I get JWT working in Autorest generated SDK? (ASP.NET Core 2.0) 【发布时间】:2018-10-29 13:10:02 【问题描述】:

我希望能够使用用户名和密码登录我的身份数据库并检索 JWT。然后我想使用 JWT 从我的 API 安全地访问数据。

发现VS2017生成的SDK代码使用了老版本的autorest,所以改用Azure Autorest

api 和 SDK 都是 ASP.NET Core 2.0

生成我使用的 SDK

AutoRest -mynamespace mytrack.Client -CodeGenerator CSharp -Modeler 
Swagger -Input swagger.json -PackageName mytrack.client -AddCredentials true

版本显示为

AutoRest code generation utility [version: 2.0.4262; node: v8.11.2]

我的测试写成

using System;
using System.Threading.Tasks;
using Microsoft.Rest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json.Linq;
using swagger; // my name space from the autorest command, not to be confused with swagger itself.
using swagger.Models;

namespace CoreClientTest

    [TestClass]
    public class MyTests
    
        [TestMethod]
        public void TestMethod1()
        
            try
            
                GetMyJob().Wait();
            
            catch (Exception e)
            
                Console.WriteLine(e);
                throw;
            
        

        private static async Task GetMyJob()
        
            var tokenRequest = new TokenRequest
            
                Username = "myusername",
                Password = "mypassword"
            ;

            var credentials = new TokenCredentials("bearer token");
            var uri = new Uri("https://localhost:44348", UriKind.Absolute);
            var tokenClient = new Track3API(uri, credentials);
            var tokenResponse = await tokenClient.ApiRequestTokenPostWithHttpMessagesAsync(tokenRequest);
            var tokenContent = await tokenResponse.Response.Content.ReadAsStringAsync();
            var tokenString = JObject.Parse(tokenContent).GetValue("token").ToString();
            var creds2 = new TokenCredentials(tokenString);
            var client2 = new Track3API(uri, creds2);
            var result = await client2.ApiJobsByIdGetWithHttpMessagesAsync(1);
            var response = result.Response;
            Console.WriteLine(response.ToString());
        
    

我可以看到结果OK,我可以看到里面的token。 我看不到返回工作

api中的方法有

[Produces("application/json")]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[Route("api/jobs")]
public class JobController : Controller



/// <summary>
/// Returns Job Header for Id
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpGet("id", Name = "Get")]
public IActionResult Get(int id)

    var header1 = new JobHeader
    
        JobNumber = "1234",
        Id = id,
        CustomerPurchaseOrderNumber = "fred"
    ;
    return Ok(header1);

【问题讨论】:

您应该在类上应用DataContract 属性,这样当 RestClient 使用服务引用时,它也会生成类型。在这里阅读——docs.microsoft.com/en-us/dotnet/api/… 您使用的是 Web API 2 吗?还是 ASP.NET Core MVC? 也添加错误堆栈跟踪,这应该有助于人们更好地查看问题 阅读dzimchuk.net/generating-clients-for-your-apis-with-autorest 【参考方案1】:

您应该在类上应用DataContract 属性,这样当 RestClient 使用服务引用时,它也会生成类型。

阅读here。

您还应该在属性上附加DatamMember 属性。见下例

[DataContract]
class Person 

    [DataMember]
    public string Name get; set; 

    [DataMember]
    public int Id get; set; 

    public Person(string name, int id)
    
        this.Name = name;
        this.Id = id;
    

当 Rest Client 使用服务时,它会在客户端为那些带有DataContract 属性的类生成类。

【讨论】:

我试过了,但在生成的模型中看不到任何差异(抱歉问题的大改写)【参考方案2】:

终于成功了。 我在Andrei Dzimchuk's blog 找到了关于设置令牌的提示

using System;
using System.Threading.Tasks;
using Microsoft.Rest;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using swagger;
using swagger.Models;

namespace CoreClientTest

    [TestClass]
    public class MyTests
    
        [TestMethod]
        public void TestMethod1()
        
            try
            
                 GetMyJob().Wait();
            
            catch (Exception e)
            
                Console.WriteLine(e);
                throw;
            
        

        private static async Task<JobHeader> GetMyJob()
        
            var tokenRequest = new TokenRequest
            
                Username = "myusername",
                Password = "mypassword"
            ;
            var credentials = new TokenCredentials("bearer token");
            var uri = new Uri("https://localhost:44348", UriKind.Absolute);
            var tokenClient = new Track3API(uri, credentials);
            var tokenResponse = await tokenClient.ApiRequestTokenPostWithHttpMessagesAsync(tokenRequest);
            var tokenContent = await tokenResponse.Response.Content.ReadAsStringAsync();
            var tokenString = JObject.Parse(tokenContent).GetValue("token").ToString();
            var creds2 = new TokenCredentials(tokenString);
            var client2 = new Track3API(uri, creds2);
            var result = await client2.ApiJobsByIdGetWithHttpMessagesAsync(1);
            string resultContent = await result.Response.Content.ReadAsStringAsync();
            var job = JsonConvert.DeserializeObject<JobHeader>(resultContent);
            Console.WriteLine(job.JobNumber);
            return job;

        
    

【讨论】:

以上是关于如何让 JWT 在 Autorest 生成的 SDK 中工作? (ASP.NET 核心 2.0)的主要内容,如果未能解决你的问题,请参考以下文章

如何降级 Autorest 扩展 - 特别是 C# 扩展?

AutoRest - 具有 C# 和 Razor 模板的 Swagger 规范代码生成器。

我可以在 blazor 中使用 Autorest 客户端吗

使用 Autorest 和 typescript 时如何取消正在进行的客户端请求?

从 Azure autorest 中生成排除方法

如何生成包含一些自定义声明的 JWT 访问令牌?