IdnentiyServer-使用客戶端憑據訪問API

情景以下:一個客戶端要訪問一個api,不須要用戶登陸,可是又不想直接暴露api給外部使用,這時能夠使用identityserver添加訪問權限。web

客戶端經過clientid和secrect訪問identitserver的Token Endpoint,獲取accesstoken;api

接着客戶端再使用accesstoken做爲頭部驗證訪問webapi。(webapi已經添加了identityserver的相關驗證)。app

 

代碼實現:其中 "http://localhost:5000"是identityserver地址,"http://localhost:5001"是api地址async

identityserver:在identityserver添加api和客戶端,以下所示:定義了一個api1資源,client客戶端。client客戶端指定爲ClientCredentials(客戶端憑據)模式,並容許其訪問api1。ide

 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以下:ui

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名稱,"http://localhost:5000"是identityserver的地址。spa

 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();
        }
    }

 添加一個須要驗證的控制器:code

 [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 });
        }
    }

 

客戶端:orm

這裏使用裏IdentityModel類庫server

實際請求以下:

1.獲取accesstoken:http://localhost:5000/connect/token?client_id=client&client_secret=secret&grant_type=client_credentials&scope=api1

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秒,即一小時

相關文章
相關標籤/搜索