IdentityServer4是什么?
IdentityServer4 是为ASP.NET Core系列量身打造的一款基于 OpenID Connect 和 OAuth 2.0 认证框架。网上对于这个框架的介绍有很多,也很详细,感兴趣的小伙伴可以去多了解。
官方文档:https://identityserver4.readthedocs.io/en/latest/
框架源码:https://github.com/IdentityServer/IdentityServer4
整体部署
使用场景
-
- 浏览器与 Web 应用程序通信
- Web 应用程序与 Web API 通信(有时自己,有时代表用户)
- 基于浏览器的应用程序与 Web API 通信
- 本机应用程序与 Web API 通信
- 基于服务器的应用程序与 Web API 通信
- Web API 与 Web API 通信(有时自己,有时代表用户)
基本术语
IdentityServer(标识服务器)
标识服务器有许多作业和功能 - 包括:
-
- 保护您的资源
- 使用本地帐户存储或通过外部标识提供程序对用户进行身份验证
- 提供会话管理和单点登录
- 管理和验证客户端
- 向客户端颁发标识和访问令牌
- 验证令牌
Users(用户)
用户是使用注册客户端访问资源的人们。
Client(客户端)
客户端用于验证用户(请求标识令牌)或访问资源(请求访问令牌)。客户端必须首先注册到标识服务器,然后才能请求令牌。
通常客户端包括 Web 应用程序、本机移动或桌面应用程序、SCA、服务器进程等。
Resources(资源)
资源是您希望使用标识服务器保护的东西,一般是一些数据和API。
资源的名称具有唯一性。
示例
本篇作为一个入门篇,我们就先从一个简单的demo开始学习吧!
1.创建IdentityServer站点
用VS2019创建一个IdentityServer站点,选择ASP.NET Core Web 应用程序,项目名称自己定.
然后安装项目的Nuget包管理器,安装包:IdentityServer4
配置 Startup的ConfigureServices方法
public void ConfigureServices(IServiceCollection services) { services.AddHttpClient(); services.AddIdentityServer().AddInMemoryApiScopes(new List<ApiScope>() { new ApiScope("api1","my api") }).AddInMemoryClients(new List<Client>() { new Client{ ClientId="my_client", AllowedGrantTypes=GrantTypes.ClientCredentials, ClientSecrets={ new Secret("aa123456bb".Sha256()) }, AllowedScopes={ "api1" } } }). AddDeveloperSigningCredential(); //使用固定的证书,防止IdentityServer4服务器重启导致以往的token失效 //AddDeveloperSigningCredential(true, "tempkey.jwk"); }
配置Configure方法
// 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.UseIdentityServer(); //app.UseRouting(); //app.UseEndpoints(endpoints => //{ // endpoints.MapGet("/", async context => // { // await context.Response.WriteAsync("Hello World!"); // }); //}); }
启动程序,在地址栏输入https://localhost:5001/.well-known/openid-configuration,如果出现以下信息,则表示配置成功
2.创建API服务器(Resources)
添加nuget包:IdentityModel
配置 Startup的ConfigureServices方法
public void ConfigureServices(IServiceCollection services) { services.AddHttpClient(); services.AddControllers(); services.AddAuthentication("Bearer").AddJwtBearer("Bearer", options => {
//identityserver4服务器地址 options.Authority = "https://localhost:5001"; options.TokenValidationParameters = new TokenValidationParameters { ValidateAudience = false }; }); // adds an authorization policy to make sure the token is for scope 'api1' services.AddAuthorization(options => {
//定义授权策略 options.AddPolicy("ApiScope", policy => { policy.RequireAuthenticatedUser();
//这里的scope的值需要在identityserver4服务器上配置 policy.RequireClaim("scope", "api1"); }); }); }
配置Configure方法
// 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(); app.UseAuthentication();//认证 app.UseAuthorization();//授权 app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }
创建一个api控制器,作为受保护的资源,在此控制器上配置授权策略,与ConfigureServices里配置的要一致
[Route("api/[controller]")] [ApiController] [Authorize("ApiScope")] public class HomeController : ControllerBase { [HttpGet] public string Get() { return "success"; } }
现在直接访问api资源服务器,将返回401未授权状态码,表明api资源服务器此时已经受到了保护.
3.创建Client
我这里用的是WebApi,小伙伴们根据不同的需求可以选择其他的客户端.
直接上代码
var client = new HttpClient();
//这里的https://localhost:5001为IdentityServer4服务器地址 var disco = await client.GetDiscoveryDocumentAsync("https://localhost:5001"); if (disco.IsError) { return Content(disco.Error); } var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest { Address = disco.TokenEndpoint, ClientId = "my_client", //需要在IdentityServer4服务器有定义 ClientSecret = "aa123456bb", //需要在IdentityServer4服务器有定义 Scope = "api1" //需要在IdentityServer4服务器有定义 }); if (tokenResponse.IsError) { return Content(tokenResponse.Error); } var apiClient = new HttpClient(); apiClient.SetBearerToken(tokenResponse.AccessToken);
//访问受保护的API资源服务器 var content = await apiClient.GetStringAsync("https://localhost:15001/api/Home"); return Content(content);
至此,一个简单的demo算是完成了,希望能给小伙伴们带来一些帮助!
鉴于本人也是刚接触这个框架不久,可能有些知识理解有误,如有不正之处,敬请指正!