情景如下:一个客户端要访问一个api,不需要用户登录,但是又不想直接暴露api给外部使用,这时可以使用identityserver添加访问权限。

客户端通过clientid和secrect访问identitserver的token endpoint,获取accesstoken;

接着客户端再使用accesstoken作为头部验证访问webapi。(webapi已经添加了identityserver的相关验证)。

代码实现:其中 “”是identityserver地址,””是api地址

identityserver:在identityserver添加api和客户端,如下所示:定义了一个api1资源,client客户端。client客户端指定为clientcredentials(客户端凭据)模式,并允许其访问api1。

public class config
 {
  // scopes define the api resources in your system
  public static ienumerable<apiresource> getapiresources()
  {
   return new list<apiresource>
   {
    new apiresource("api1", "my api")
   };
  }
  // clients want to access resources (aka scopes)
  public static ienumerable<client> getclients()
  {
   // client credentials client
   return new list<client>
   {
    new client
    {
     clientid = "client",
     allowedgranttypes = granttypes.clientcredentials,
     clientsecrets = 
     {
      new secret("secret".sha256())
     },
     allowedscopes = { "api1" }
    }
   };
  }
 }

在startup配置identityserver如下:

public class startup
 {
  public void configureservices(iservicecollection services)
  {
   // configure identity server with in-memory stores, keys, clients and scopes
   services.addidentityserver()
    .adddevelopersigningcredential()
    .addinmemoryapiresources(config.getapiresources())
    .addinmemoryclients(config.getclients());
  }
  public void configure(iapplicationbuilder app, ihostingenvironment env)
  {
   if (env.isdevelopment())
   {
    app.usedeveloperexceptionpage();
   }
   app.useidentityserver();
  }
 }

webapi:在api添加identityserver的验证,代码如下,其中定义了同样的api名称,””是identityserver的地址。

public class startup
 {
  public void configureservices(iservicecollection services)
  {
   services.addmvccore()
    .addauthorization()
    .addjsonformatters();
   services.addauthentication("bearer")
    .addidentityserverauthentication(options =>
    {
     options.authority = "http://localhost:5000";
     options.requirehttpsmetadata = false;
     options.apiname = "api1";
    });
  }
  public void configure(iapplicationbuilder app)
  {
   app.useauthentication();
   app.usemvc();
  }
 }

 添加一个需要验证的控制器:

 [route("[controller]")]
 [authorize]
 public class identitycontroller : controllerbase
 {
  [httpget]
  public iactionresult get()
  {
   return new jsonresult(from c in user.claims select new { c.type, c.value });
  }
 }

客户端:

这里使用里identitymodel类库

实际请求如下:

1.获取accesstoken:

2.请求api1

http://localhost:5001/identity
headers
authorization:accesstoken

public class program
 {
  public static void main(string[] args) => mainasync().getawaiter().getresult();
  private static async task mainasync()
  {
    //获取identitserver的各个端点地址
   var disco = await discoveryclient.getasync("http://localhost:5000");
   if (disco.iserror)
   {
    console.writeline(disco.error);
    return;
   }
   //获取具有api1访问权限的accesstoken
   var tokenclient = new tokenclient(disco.tokenendpoint, "client", "secret");
   var tokenresponse = await tokenclient.requestclientcredentialsasync("api1");
   if (tokenresponse.iserror)
   {
    console.writeline(tokenresponse.error);
    return;
   }
   console.writeline(tokenresponse.json);
   console.writeline("\n\n");
   //设置accesstoken为http请求头,并访问api1
   var client = new httpclient();
   client.setbearertoken(tokenresponse.accesstoken);
   var response = await client.getasync("http://localhost:5001/identity");
   if (!response.issuccessstatuscode)
   {
    console.writeline(response.statuscode);
   }
   else
   {
    var content = await response.content.readasstringasync();
    console.writeline(jarray.parse(content));
   }
  }
 }

ps:

1.这里默认的accesstoken为jwt格式,客户端访问api时,api只需要在启动的时候访问identity获取秘钥即可。若为referencetoken,客户端访问api时,api需要授权访问的都会再请求一次identityserver,,而且api必须设置秘钥,client设置accesstokentype属性为reference。

2.可自定义accesstokenlifetime(token存活时间),默认是3600秒,即一小时

总结

以上所述是www.887551.com给大家介绍的idnentiyserver-使用客户端凭据访问api,希望对大家有所帮助