Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/266.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用自动测试C#客户端访问带有承载令牌的Web API-令牌凭据不起作用_C#_Asp.net Web Api_Adal_Bearer Token_Autorest - Fatal编程技术网

使用自动测试C#客户端访问带有承载令牌的Web API-令牌凭据不起作用

使用自动测试C#客户端访问带有承载令牌的Web API-令牌凭据不起作用,c#,asp.net-web-api,adal,bearer-token,autorest,C#,Asp.net Web Api,Adal,Bearer Token,Autorest,编辑10/24 我认为这很可能是用户错误——在深入讨论这个问题之前,请参阅下面我的答案以获得补救 TL;医生: 对于我的OAuth 2.0代码流 为什么我的TokenCredentials不能与我的自动测试客户端一起工作? 我没有收到应用于请求/无授权标头集的承载令牌 我知道我的管道已经开始工作了。 使用非自动测试客户机的代码,我可以成功地获取我的access\u令牌,并可以从受保护的Web API项目中获取JSON。。所以我排除了所有先决条件。。我知道我的管道工作 我的自动测试设置.. 1.)

编辑10/24 我认为这很可能是用户错误——在深入讨论这个问题之前,请参阅下面我的答案以获得补救

TL;医生: 对于我的OAuth 2.0代码流

为什么我的
TokenCredentials
不能与我的自动测试客户端一起工作? 我没有收到应用于请求/无授权标头集的承载令牌

我知道我的管道已经开始工作了。

使用非自动测试客户机的代码,我可以成功地获取我的
access\u令牌
,并可以从受保护的Web API项目中获取JSON。。所以我排除了所有先决条件。。我知道我的管道工作

我的自动测试设置..

1.)从GitHub v1.1.0下载

2.)将我的swagger JSON下载到磁盘,另存为
swagger.JSON

3.)运行此命令行以生成C#文件:

autorest--input file=swagger.json--csharp--output folder=MyCorp\u ApiClient\u Tsl--namespace='MyCorp.ApiClient'--添加凭据

4.)将生成的类复制到我的.NET 4.6.2网站中

5.)这些是我的拿手好戏:

- Microsoft.Rest.ClientRuntime version="2.3.8" 
- Microsoft.Rest.ClientRuntime.Azure.Authentication version="2.3.1" 
- Microsoft.IdentityModel.Clients.ActiveDirectory version="2.28.3" 
以下是不起作用的地方:

   AdalTokenHelper tokenHelper = new AdalTokenHelper();//helper code further below

    string token = await tokenHelper.GetTokenString();
    var svcClientCreds = new TokenCredentials(token, "Bearer");

    client = new MyCorp.ApiClient(new Uri(apiRsrcUrl), svcClientCreds, 
    new DelegatingHandler[] { new MyAzureTracingHandler() });

    //make call to OData controller...        
    MyCorp.ApiClient.Models.ODataResponseListStatus statusList = await client.Status.GetStatusAsync(expand: "StatusType",cancellationToken: defaultCancelThreadToken);

    return View(statusList.Value);
    private string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
    private string appKey = ConfigurationManager.AppSettings["ida:ClientSecret"];
    private string tslResourceID = ConfigurationManager.AppSettings["ross:TslWebApiResourceId"];
    private static string loginRedirectUri = ConfigurationManager.AppSettings["ross:LoginRedirectUri"];

    private AuthenticationContext authContext;
    private AuthenticationResult authenticationResult;

    public async Task<string> GetTokenString()
    {
        string signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
        string tenantID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
        string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;

        try
        {
            // get a token for the Graph without triggering any user interaction (from the cache, via multi-resource refresh token, etc)
            ClientCredential clientcred = new ClientCredential(clientId, appKey);

            // initialize AuthenticationContext with the token cache of the currently signed in user, as kept in the app's database
            authContext = new AuthenticationContext(Startup.Authority, new ADALTokenCache(userObjectID));


            UserIdentifier userIdentifier = new UserIdentifier(userObjectID, UserIdentifierType.UniqueId);

            authenticationResult = await authContext.AcquireTokenSilentAsync(tslResourceID, clientcred, userIdentifier);
        }
        catch(AdalException ex)
        {
            throw ex;
        }
        return authenticationResult.AccessToken;
    }
我已经尝试了以上的变体,使用了不同的ctor of
TokenCredentials
,但不管怎样,我可以将断点放在
MyAzureTracingHandler
中,并看到请求没有应用授权头。。因此,我得到了预期的
401未经授权的
响应

如果我修改
MyAzureTracingHandler
以接受我的
TokenCredentials
实例,那么我可以强制请求应用适当的承载令牌

这是可行的,但感觉有点像黑客:

   AdalTokenHelper tokenHelper = new AdalTokenHelper();//helper code further below

    string token = await tokenHelper.GetTokenString();
    var svcClientCreds = new TokenCredentials(token, "Bearer");

    client = new MyCorp.ApiClient(new Uri(apiRsrcUrl), svcClientCreds, 
    new DelegatingHandler[] { new MyAzureTracingHandler() });

    //make call to OData controller...        
    MyCorp.ApiClient.Models.ODataResponseListStatus statusList = await client.Status.GetStatusAsync(expand: "StatusType",cancellationToken: defaultCancelThreadToken);

    return View(statusList.Value);
    private string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
    private string appKey = ConfigurationManager.AppSettings["ida:ClientSecret"];
    private string tslResourceID = ConfigurationManager.AppSettings["ross:TslWebApiResourceId"];
    private static string loginRedirectUri = ConfigurationManager.AppSettings["ross:LoginRedirectUri"];

    private AuthenticationContext authContext;
    private AuthenticationResult authenticationResult;

    public async Task<string> GetTokenString()
    {
        string signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
        string tenantID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
        string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;

        try
        {
            // get a token for the Graph without triggering any user interaction (from the cache, via multi-resource refresh token, etc)
            ClientCredential clientcred = new ClientCredential(clientId, appKey);

            // initialize AuthenticationContext with the token cache of the currently signed in user, as kept in the app's database
            authContext = new AuthenticationContext(Startup.Authority, new ADALTokenCache(userObjectID));


            UserIdentifier userIdentifier = new UserIdentifier(userObjectID, UserIdentifierType.UniqueId);

            authenticationResult = await authContext.AcquireTokenSilentAsync(tslResourceID, clientcred, userIdentifier);
        }
        catch(AdalException ex)
        {
            throw ex;
        }
        return authenticationResult.AccessToken;
    }
我更改了以下内容的原始客户端实例化片段:

 client = new ApiClient(new Uri(apiRsrcUrl), svcClientCreds, 
 new DelegatingHandler[] { new MyAzureTracingHandler() });
为此:

 client = new ApiClient(new Uri(apiRsrcUrl), svcClientCreds, 
 new DelegatingHandler[] { new MyAzureTracingHandler(svcClientCreds) });
MyAzureTracingHander
SendAsync
方法中,我执行以下操作:

await svcClientCreds.ProcessHttpRequestAsync(request, cancellationToken);
我做错什么了吗?我认为在实例化我的客户机时,我不必两次传递
ServiceClientCredentials

附录A-通过ADAL获取访问令牌:

   AdalTokenHelper tokenHelper = new AdalTokenHelper();//helper code further below

    string token = await tokenHelper.GetTokenString();
    var svcClientCreds = new TokenCredentials(token, "Bearer");

    client = new MyCorp.ApiClient(new Uri(apiRsrcUrl), svcClientCreds, 
    new DelegatingHandler[] { new MyAzureTracingHandler() });

    //make call to OData controller...        
    MyCorp.ApiClient.Models.ODataResponseListStatus statusList = await client.Status.GetStatusAsync(expand: "StatusType",cancellationToken: defaultCancelThreadToken);

    return View(statusList.Value);
    private string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
    private string appKey = ConfigurationManager.AppSettings["ida:ClientSecret"];
    private string tslResourceID = ConfigurationManager.AppSettings["ross:TslWebApiResourceId"];
    private static string loginRedirectUri = ConfigurationManager.AppSettings["ross:LoginRedirectUri"];

    private AuthenticationContext authContext;
    private AuthenticationResult authenticationResult;

    public async Task<string> GetTokenString()
    {
        string signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
        string tenantID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
        string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;

        try
        {
            // get a token for the Graph without triggering any user interaction (from the cache, via multi-resource refresh token, etc)
            ClientCredential clientcred = new ClientCredential(clientId, appKey);

            // initialize AuthenticationContext with the token cache of the currently signed in user, as kept in the app's database
            authContext = new AuthenticationContext(Startup.Authority, new ADALTokenCache(userObjectID));


            UserIdentifier userIdentifier = new UserIdentifier(userObjectID, UserIdentifierType.UniqueId);

            authenticationResult = await authContext.AcquireTokenSilentAsync(tslResourceID, clientcred, userIdentifier);
        }
        catch(AdalException ex)
        {
            throw ex;
        }
        return authenticationResult.AccessToken;
    }
private string clientId=ConfigurationManager.AppSettings[“ida:clientId”];
私有字符串appKey=ConfigurationManager.AppSettings[“ida:ClientSecret”];
私有字符串tslResourceID=ConfigurationManager.AppSettings[“ross:TslWebApiResourceId”];
私有静态字符串LoginDirectUri=ConfigurationManager.AppSettings[“ross:LoginDirectUri”];
私有身份验证上下文authContext;
私有AuthenticationResult AuthenticationResult;
公共异步任务GetTokenString()
{
字符串signedInUserID=ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
字符串tenantID=ClaimsPrincipal.Current.FindFirst(“http://schemas.microsoft.com/identity/claims/tenantid1.价值;
字符串userObjectID=ClaimsPrincipal.Current.FindFirst(“http://schemas.microsoft.com/identity/claims/objectidentifier1.价值;
尝试
{
//在不触发任何用户交互的情况下获取图形的令牌(从缓存,通过多资源刷新令牌等)
ClientCredential clientcred=新的ClientCredential(clientId,appKey);
//使用保存在应用程序数据库中的当前登录用户的令牌缓存初始化AuthenticationContext
authContext=新的AuthenticationContext(Startup.Authority,新的ADALTokenCache(userObjectID));
UserIdentifier UserIdentifier=新的UserIdentifier(userObjectID,UserIdentifierType.UniqueId);
authenticationResult=等待authContext.AcquireTokenSilentAsync(tslResourceID、clientcred、userIdentifier);
}
捕获(ADALEX)
{
掷骰子;
}
返回authenticationResult.AccessToken;
}

虽然我相信我用
--add credentials
运行了我的
autorest
命令,但我可能使用了较旧的语法<代码>--AddCredentials true

我也没有像文档建议的那样运行
autorest--reset

其中一个就是罪魁祸首,因为现在我的1.1.0自动测试安装正在正确生成所有内容。

引用了
--reset
标志。
--add credentials
位位于