前言
客戶端授權模,客戶端直接向Identity Server申請token並訪問資源。客戶端授權模式比較適用於服務之間的通信。
搭建Identity服務
新建名為 IdentityServer
的WebApi空項目,設置端口為5000,作為我們的授權認證服務。
新建名為 Api
的WebApi空項目,設置端口為5001,作為我們的Api資源。
通過NuGet安裝 IdentityServer4
或者通過程序包管理執行 Install-Package IdentityServer4
安裝依賴包。
新一個 Config
文件來定義Identity資源
using System.Collections.Generic;
using IdentityServer4;
using IdentityServer4.Models;
namespace IdentityServer
{
public static class Config
{
public static IEnumerable<IdentityResource> GetIdentityResourceResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(), //必須要添加,否則報無效的scope錯誤
};
}
// scopes define the API resources in your system
public static IEnumerable<ApiResource> GetApiResources()
{
//api資源({資源名稱}{描述})
return new List<ApiResource>
{
new ApiResource("Api", "Api"),
};
}
// clients want to access resources (aka scopes)
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
new Client
{
//客戶端id,必須唯一
ClientId = "client_a",
//授權方式,這里采用的是客戶端認證模式,只要ClientId,以及ClientSecrets正確即可訪問對應的AllowedScopes里面的api資源
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedScopes =
{
"Api",
}
}
};
}
}
}
在 Startup
中配置IdentityServer
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace IdentityServer
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
//注入DI
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryApiResources(Config.GetApiResources())//Api資源信息
.AddInMemoryClients(Config.GetClients());//客戶端信息
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
//放入HTTP管道中
app.UseIdentityServer();
}
}
}
運行當前項目,並訪問 http://localhost:5000/.well-known/openid-configuration
就會看到當前IdentityServer的一些信,首次啟動會創建一個名為tempkey.rsa
的文件,里面保存的是你的簽名密鑰。
定義Api資源
通過NuGet安裝 IdentityServer4.AccessTokenValidation
或者通過程序包管理執行 IInstall-Package IdentityServer4.AccessTokenValidation
安裝依賴包。
在 Api
項目中新增一個ValuesController
並添加一個 Print
接口 Authorize
表示該接口被身份認證所保護
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Api.Controllers
{
[Route("api/[controller]")]
public class ValuesController : Controller
{
[HttpGet("Print")]
[Authorize]
public ActionResult Print()
{
return new JsonResult("hello word");
}
}
}
在 Startup
中把身份認證服務注入DI,並放入HTTP管道。
uusing Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace Api
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
//將身份認證注入到DI
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.Audience = "Api";
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
//身份認證添加到HTTP管道
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
測試效果
我們同時運行兩個項目。這時候我們直接訪問Api資源。會直接拋出401(用戶沒有權限訪問)
我們用配置的client向IdentityServer申請token來訪問Api資源
client_id - 我們配置的客戶端id
client_secret - 簽名密鑰。
grant_type - 授權模式
access_token - 訪問令牌
expires_in - 過去時間(秒)
token_type - 令牌類型
scope - 可以訪問資源名稱
使用資源訪問Api資源,在Hraders中加入 authorization
傳入剛申請的token(Bearer后面有一個空格)