【问题标题】:How to get access token from Identity Server by passing username and password?如何通过传递用户名和密码从 Identity Server 获取访问令牌?
【发布时间】:2018-01-05 12:41:51
【问题描述】:

我们正在使用身份服务器为我们的网络服务生成访问令牌。我们还添加了招摇。 但我们面临的问题是,通过使用代码 sn-p 生成访问令牌以实现 API 自动化。 有没有使用用户名和密码自动获取访问令牌的方法?

谢谢。

【问题讨论】:

    标签: .net api automation automated-tests identityserver3


    【解决方案1】:

    我解决这个问题的方法是添加一个客户端凭据客户端,如果有一个配置的测试客户端密码,我只在测试环境中配置这个密码,但显然不在更高的环境中,这意味着客户端永远不会被添加到那里。

    因此,在您的 appsettings.{property_environment}.settings 或通过环境变量设置客户端密码,然后您可以在 IdentityServer 配置中添加:

    //attempt to get the test client secret
    var testClientSecret = configuration["TestClientSecret"];
    if (!String.IsNullOrWhiteSpace(testClientSecret))
    {
        clients.Add(new Client
        {
            ClientId = "MyTestClient",
    
            AllowedGrantTypes = GrantTypes.ClientCredentials,
    
            ClientSecrets =
            {
                new Secret(testClientSecret.Sha256())
            },
    
            AllowedScopes = { "MyApiScope", "MyOtherApiScope", "etc." }
        });
    };
    

    然后我有一个 Postman 测试集合,它首先 POST 到:

    https://{{idp_base_url}}/connect/token
    

    使用带有测试客户端名称和密码的用户名的基本身份验证作为客户端密码(其中 {{idp_base_url}} 是一个邮递员环境变量,其中包含适用于该环境的 IdentityServer 主机)。

    然后我运行一些测试,同时将访问令牌存储到 API:

    //tests...
    var tokenData = JSON.parse(responseBody);
    //more tests...
    postman.setEnvironmentVariable("cc_token", tokenData.access_token);
    

    然后,集合中的后续测试可以使用上面的 Postman 环境变量使用此令牌和不记名令牌 auth 标头运行您的 API 测试:

    【讨论】:

      【解决方案2】:

      首先声明一个名为Token的类。

      public class Token
      {
          [JsonProperty("access_token")]
          public string AccessToken { get; set; }
      
          [JsonProperty("token_type")]
          public string TokenType { get; set; }
      
          [JsonProperty("expires_in")]
          public int ExpiresIn { get; set; }
      
          [JsonProperty("userName")]
          public string Username { get; set; }
      
          [JsonProperty(".issued")]
          public string IssuedAt { get; set; }
      
          [JsonProperty(".expires")]
          public string ExpiresAt { get; set; }
      }
      

      在 Postman 中,我们在 POST 方法中使用用户名、密码和 grant_type 从 baseURl/token uri 生成 access_token。要知道您应该使用哪个 url,请检查 App_Start 文件夹中的 Startup.Auth.cs 文件。

      OAuthOptions = new OAuthAuthorizationServerOptions
      {
           TokenEndpointPath = new PathString("/Token"),
           .....
      }
      

      适当的 URL 由 PathString() 构造函数中的字符串确定。

      一旦您知道要调用哪个 url,现在要获取访问令牌,请考虑以下代码。

      var keyValues = new List<KeyValuePair<string, string>>
      {
          new KeyValuePair<string, string>("username", username),
          new KeyValuePair<string, string>("password",password),
          new KeyValuePair<string, string>("grant_type", "password")
      };
      
      var request = new HttpRequestMessage(HttpMethod.Post, "baseUrl/Token");
      
      request.Content = new FormUrlEncodedContent(keyValues);
      
      var client = new HttpClient();
      
      var response = await client.SendAsync(request);
      
      var content = await response.Content.ReadAsStringAsync();
      var accessTokenVar = JsonConvert.DeserializeObject<AuthenticationToken>(content);
      

      现在可以使用 accessTokenVar 访问访问令牌。

      【讨论】:

        【解决方案3】:

        另一种方法是使用IdentityModel NuGet 来获取令牌。示例:

        var client = new HttpClient();
        var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
        {
            Address = $"{IdentityServerUrl}/connect/token",
            ClientId = "THE_CLIENT_ID",
            ClientSecret = IdentityServerPass,
            Scope = "api.read"
        
        }).ConfigureAwait(false);
        tokenResponse.HttpResponse.EnsureSuccessStatusCode();
        

        【讨论】:

        • 这应该是公认的答案。谢谢!!
        猜你喜欢
        • 2018-07-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-18
        • 1970-01-01
        • 2012-04-28
        • 1970-01-01
        • 2018-12-25
        相关资源
        最近更新 更多