简介

  本人做微服务项目也有一段时间了,在微服务中让我感触颇深的就是这个IdentityServer4了,ID4(IdentityServer4的简称)中涉及的概念颇多,本文不谈概念(我怕读者没耐心看下去),在这分享下我个人的使用心得。

目录

  1. ID4简介

  2. ID4使用

ID4简介

  相信大家都知道面向对象中的封装(把通用的功能封装起来,减少程序中大量重复代码),我们知道在一个单体系统中有很多的重复模块,例如:身份认证、权限控制检查等,在单体系统中,这些都可以使用aop统一在一个地方控制。而在分布式系统,每个系统都需要进行身份认证、权限检查等。这时,每个系统都得写一套同样的代码来进行这些控制,我们能不能像单体系统那样在一个地方进行这些流程呢?这时我们可以使用IdentityServer4来实现。

  IdentityServer4是一个集成 身份认证和授权 的组件,使用OpenId Connect(身份识别框架) 和 Auth2.0(授权框架)来进行身份认证和授权的。

ID4使用

我这里只列出几个主要的类,其它,可以下载项目来看。关于如何使用,代码有点多,我比较懒,就没怎么讲解,感兴趣的小伙伴可以加个QQ:1983702356 来讨论下。

WEBAPPLICATION1 (IDENTITYSERVER4)项目,安装 INSTALL-PACKAGE IDENTITYSERVER4 -VERSION 2.5.0,

  1. 以下几个类比较关键

    1. Config.cs。主要是获取身份资源

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      public class Config
      {
      public static IEnumerable<IdentityResource> GetIdentityResources()
      {
      return new List<IdentityResource>
      {
      new IdentityResources.OpenId(), //必须要添加,否则报无效的 scope 错误
      new IdentityResources.Profile(),
      new IdentityResources.Email()
      };
      }
      }
    2. TestClientStore.cs 加载IdentityServer4的client

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      /// <summary>
      /// 加载IdentityServer4的client
      /// </summary>
      public class TestClientStore : IClientStore
      {
      /// <summary>
      /// Service层中的一个接口
      /// </summary>
      public IClientService ClientSvc { get; set; }

      public TestClientStore(IClientService ClientSvc)
      {
      this.ClientSvc = ClientSvc;
      }
      public async Task<Client> FindClientByIdAsync(string clientId)
      {
      var dto = await ClientSvc.FindClientByIdAsync(clientId);
      if (dto==null)
      {
      return null;
      }
      var scopes = dto.APIResources.Select(e => e.Name).ToList();
      scopes.Add(IdentityServerConstants.StandardScopes.OpenId);
      scopes.Add(IdentityServerConstants.StandardScopes.Profile);
      return new Client
      {
      ClientId = dto.Client.Id,//API账号、客户端Id
      AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
      ClientSecrets =
      {
      new Secret(dto.Client.Secret.Sha256())//秘钥
      },
      AllowedScopes = scopes//这个账号支持访问哪些应用
      };
      }
      }
    3. TestReourceStore.cs,加载IdentityServer的APIResource

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      /// <summary>
      /// 加载IdentityServer的APIResource
      /// </summary>
      public class TestReourceStore : IResourceStore
      {
      public IApiResourceService resourceSvc { get; set; }
      public TestReourceStore(IApiResourceService resourceSvc)
      {
      this.resourceSvc = resourceSvc;
      }
      public async Task<ApiResource> FindApiResourceAsync(string name)
      {
      var entity = await resourceSvc.GetByNameAsync(name);
      return new ApiResource(entity.Name,entity.DisplayName);
      }

      public async Task<IEnumerable<ApiResource>> FindApiResourcesByScopeAsync(IEnumerable<string> scopeNames)
      {
      var list = await resourceSvc.GetDatasByNamesAsync(scopeNames);
      return list.Select(e=>new ApiResource(e.Name,e.DisplayName));
      }

      public async Task<IEnumerable<IdentityResource>> FindIdentityResourcesByScopeAsync(IEnumerable<string> scopeNames)
      {
      return Config.GetIdentityResources().Where(e => scopeNames.Contains(e.Name)).ToList();
      }

      public async Task<Resources> GetAllResourcesAsync()
      {
      var list = await resourceSvc.GetNoramlAll();

      var resouces = list.Select(e => new ApiResource(e.Name, e.DisplayName)).ToList();
      return new Resources
      {
      ApiResources = resouces
      };

      }
      }
    4. TestResourceOwnerPasswordValidator.cs,IdentityServer4登录验证

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      /// <summary>
      /// IdentityServer4登录验证
      /// </summary>
      public class TestResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
      {
      public IUserService UserSvc { get; set; }
      public TestResourceOwnerPasswordValidator(IUserService UserSvc)
      {
      this.UserSvc = UserSvc;
      }
      public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
      {
      string account = context.UserName;
      string pwd = context.Password;

      var loginResult = await UserSvc.Login(account, pwd);

      if (loginResult == null)
      {
      context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "invalid custom credential");
      return;
      }
      context.Result = new GrantValidationResult(
      subject: context.UserName,
      authenticationMethod: "custom",
      claims: new Claim[] {
      new Claim("Name",context.UserName),
      new Claim("UserId",loginResult.Id),
      new Claim("Roles","Admin,Contact"), //模拟获取登录用户的角色信息
      new Claim("Premissions","List,Delete") //模拟获取登录用户的权限信息
      });

      }
      }
    5. ProfileService.cs,用户信息

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      public class ProfileService : IProfileService
      {
      public async Task GetProfileDataAsync(ProfileDataRequestContext context)
      {
      var claims = context.Subject.Claims.ToList();
      context.IssuedClaims = claims.ToList();
      }

      public async Task IsActiveAsync(IsActiveContext context)
      {
      context.IsActive = true;
      }
      }
  1. Startup类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
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.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

//services.AddAuthentication("Bearer")
// .AddIdentityServerAuthentication(options =>
// {
// options.Authority = "http://localhost:9500";//identity server 地址
// options.RequireHttpsMetadata = false;
// });

string conStr = Configuration["connectionString"];
services.AddDbContext<TestDbContext>(options =>
{
options.UseMySql(conStr);
});

///依赖注入Service层
AddSigletons(services);

#region ID4服务配置
var id4Build = services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryIdentityResources(Config.GetIdentityResources());
//加载apiresource
id4Build.Services.AddTransient<IResourceStore, TestReourceStore>();
//加载client
id4Build.Services.AddTransient<IClientStore, TestClientStore>();
//登录验证
id4Build.Services.AddTransient<IResourceOwnerPasswordValidator, TestResourceOwnerPasswordValidator>();
//加载profile。profile是用户信息
id4Build.Services.AddTransient<IProfileService, ProfileService>();
#endregion

//services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

}

public void AddSigletons(IServiceCollection services)
{
var assem = Assembly.Load("Test.Service");
var list = assem.GetTypes().Where(e => e.IsAbstract == false && typeof(ISignFac).IsAssignableFrom(e));
foreach (var instanType in list)
{
foreach (var item in instanType.GetInterfaces())
{
services.AddSingleton(item, instanType);
}
}
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
//插入id4中间件
app.UseIdentityServer();
//app.UseAuthentication();
//app.UseStaticFiles();
//app.UseCookiePolicy();
//app.UseMvc(routes =>
//{
// routes.MapRoute(
// name: "default",
// template: "{controller=Home}/{action=Index}/{id?}");
//});

}
}
  1. WebApplication3 API项目,修改Startup,并添加一个控制器,在方法上打上一个标签

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56

    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.AddAuthentication("Bearer")
    .AddIdentityServerAuthentication(options =>
    {
    options.Authority = "http://localhost:9500";//identity server 地址
    options.RequireHttpsMetadata = false;
    });

    string conStr = Configuration["connectionString"];
    services.AddDbContext<TestDbContext>(options =>
    {
    options.UseMySql(conStr);
    });

    ///依赖注入Service层
    AddSigletons(services);
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    }

    public void AddSigletons(IServiceCollection services)
    {
    var assem = Assembly.Load("Test.Service");
    var list = assem.GetTypes().Where(e => e.IsAbstract == false && typeof(ISignFac).IsAssignableFrom(e));
    foreach (var instanType in list)
    {
    foreach (var item in instanType.GetInterfaces())
    {
    services.AddSingleton(item, instanType);
    }
    }
    }
    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
    if (env.IsDevelopment())
    {
    app.UseDeveloperExceptionPage();
    }
    app.UseAuthentication();

    app.UseMvc();
    }
    }

运行CONSOLEAPP1控制台项目, 生成数据库,添加几条数据

运行效果

  1. 在 WebApplication1 目录下运行cmd命令 dotnet run ,启动IdentitServer4,端口是9500

  2. 运行项目 WebApplication3 ,端口是5000

  3. 当我们直接调用 WebApplication3 API中的方法时,发现返回状态码为 401

  4. 请求Id4,复制返回的 access_token

  5. 再请求WebApplication3 API,并在报文头带上token

结束语

  个人认为我这种使用方式和其它使用方式最大的好处就是,可以写一个IdentityServer4的Client、APIResource增删改查,然后因为每次请求的时候都是从数据库读取数据的,如果数据被修改了,会立即生效。

IdentityServer4的最佳使用的更多相关文章

  1. IdentityServer4关于多客户端和API的最佳实践【含多类型客户端和API资源,以及客户端分组实践】【下】

    经过前两篇文章你已经知道了关于服务器搭建和客户端接入相关的基本资料,本文主要讲述整个授权系统所服务的对象,以ProtectApi资源为演示 目标: 1)实现多资源服务器针对请求的token校验,接入I ...

  2. IdentityServer4实战 - 谈谈 JWT 的安全策略

    一.前言 众所周知,IdentityServer4 默认支持两种类型的 Token,一种是 Reference Token,一种是 JWT Token .前者的特点是 Token 的有效与否是由 To ...

  3. ASP.NET Core身份认证服务框架IdentityServer4(2)-整体介绍

    一.整体情况 现代应用程序看起来更像这个: 最常见的相互作用: 浏览器与Web应用程序的通信 Browser -> Web App Web应用程序与Web API通信 基于浏览器的应用程序与We ...

  4. IdentityServer4 中文文档 -1- (简介)背景

    IdentityServer4 中文文档 -1- (简介)背景 原文:http://docs.identityserver.io/en/release/intro/big_picture.html 目 ...

  5. IdentityServer4 中文文档 -8- (快速入门)设置和概览

    IdentityServer4 中文文档 -8- (快速入门)设置和概览 原文:http://docs.identityserver.io/en/release/quickstarts/0_overv ...

  6. IdentityServer4中文文档

    欢迎IdentityServer4 IdentityServer4是ASP.NET Core 2的OpenID Connect和OAuth 2.0框架. 它在您的应用程序中启用以下功能: 认证即服务 ...

  7. 【IdentityServer4文档】- 启动和概览

    启动和概览 有两种基本的方式来启动一个新的 IdentityServer 项目: 从空项目开始(从头开始) 从 Visual Studio 的 ASP.NET Identity 模板开始 假如您从头开 ...

  8. 【IdentityServer4文档】- 整体情况

    整体概况 大多数现代应用程序看起来或多或少像这样: 最常见的交互是: 浏览器与 Web 应用程序进行通信 Web 应用程序与 Web API 进行通信(有时是Web应用程序自己发起,有时代表用户发起) ...

  9. IdentityServer4实战 - 谈谈 JWT Token 的安全策略

    原文:IdentityServer4实战 - 谈谈 JWT Token 的安全策略 一.前言 众所周知,IdentityServer4 默认支持两种类型的 Token,一种是 Reference To ...

  10. asp.net core IdentityServer4 概述

    概览 现代应用程序看上去大都是这样的: 最常见的交互是: 浏览器与Web应用程序通信 Web应用程序与Web API通信(有时是独立的,有时是代表用户的) 基于浏览器的应用程序与Web API通信 本 ...

随机推荐

  1. 使用python连接elasticsearch

    官方文档地址:https://www.elastic.co/guide/en/elasticsearch/client/python-api/current/overview.html 安装的时候注意 ...

  2. 关于linux的一点好奇心(五):进程线程的创建

    一直以来,进程和线程的区别,这种问题一般会被面试官拿来考考面试者,可见这事就不太简单.简单说一点差异是,进程拥有独立的内存资源信息,而线程则共享父进程的资源信息.也就是说线程不拥有内存资源,所以对系统 ...

  3. v-infinite-scroll无限滚动

    v-infinite-scroll="loadMore"表示回调函数是loadMore infinite-scroll-disabled="busy"表示由变量 ...

  4. PAT (Basic Level) Practice 1007 素数对猜想 分数 20

    让我们定义dn​为:dn​=pn+1​−pn​,其中pi​是第i个素数.显然有d1​=1,且对于n>1有dn​是偶数."素数对猜想"认为"存在无穷多对相邻且差为2的 ...

  5. 关于Oracle-VM-VirtualBox的安装与说明

    VirtualBox 是一款开源虚拟机软件.VirtualBox 是由德国 Innotek 公司开发,由Sun Microsystems公司出品的软件 使用Qt编写,在 Sun 被 Oracle 收购 ...

  6. SSM项目环境快速搭建

    SSM项目的环境搭建 环境搭建的目标 工程创建 创建父工程 创建空 maven工程 xxx-parent 作为父工程 修改父工程中的 pom.xml <!--?xml version=" ...

  7. LcdTools如何添加图片画面到PX01显示

    LcdTools打开点屏工程,切到"画面设置"栏,在"画面资源"栏选择"Picture"画面,先设置图片ID编号(此编号用于PG对图片编号, ...

  8. Istio Ambient Mesh七层服务治理图文详解

    摘要:本文主要集中剖析Ambient mesh七层服务治理相关内容. 本文分享自华为云社区<Istio Ambient Mesh七层服务治理图文详解>,作者:华为云云原生团队. 由于Amb ...

  9. Kubernetes核心技术Pod

    Kubernetes核心技术Pod Pod概述 Pod是K8S系统中可以创建和管理的最小单元,是资源对象模型中由用户创建或部署的最小资源对象模型,也是在K8S上运行容器化应用的资源对象,其它的资源对象 ...

  10. 【云原生 · Kubernetes】部署博客系统

    [云原生 · Kubernetes]Kubernetes运维 接着上次的内容,后续来了! (1)配置NFS服务 master节点安装NFS与RPC服务: # yum install -y nfs-ut ...