简介

  本人做微服务项目也有一段时间了,在微服务中让我感触颇深的就是这个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. JSP实现登录删除添加星座等(带样式)

    功能要求 1.完成两个页面 2.第一个登陆页面login. jsp 3.第二个用户管理页面useManage. jsp 4.有登录功能(能进行用户名密码的校验,用户名若为自己的学号密码为班级号,允许登 ...

  2. How to get the return value of the setTimeout inner function in js All In One

    How to get the return value of the setTimeout inner function in js All In One 在 js 中如何获取 setTimeout ...

  3. Windows docker环境安装

    前期准备 1.hyper-v功能 win10家庭版没有提供hyper-v的问题可通过如下脚本解决,保存为bat并运行重启电脑即可. pushd "%~dp0" dir /b %Sy ...

  4. 腾讯云短信SDK-精简版

    /** * 腾讯云短信SDK-精简版 * 本模块使用-向腾讯云短信服务器发送请求 * @return json 腾讯服务器返回值-json字符串 */ private function send_sm ...

  5. 安装与配置FTP服务器

    概:   文件传输协议 (File Transfer Protocol,FTP),用于在网络上进行文件传输的协议.如果用户需要将文件从本机发送到另一台计算机,可以使用FTP上传操作:反之,用户可以使用 ...

  6. Vue学习之--------el与data的两种写法、MVVM模型、数据代理(2022/7/5)

    文章目录 1.el与data的两种写法 1.1.基础知识 1.2.代码实例 1.3.页面效果 2.MVVM模型 2.1. 基础知识 2.2 .代码实例 2.3.页面效果 3.数据代理 3.1. 基础知 ...

  7. PaddleOCR-EAST

    目录 EAST Abstract Train PreProcess Architecture Backbone Neck Head Loss Dice Loss SmoothL1 Loss Infer ...

  8. 测试架构师CAP原理(最简单)

    测试架构师CAP原理(最简单) 很多人都不是很了解CAP理论,其实CAP很简单,不要想复杂了! C:一致性,就是数据一致性,就是数据不出错! A:可用性,就是说速度快,不延迟,无论请求成功失败都很快返 ...

  9. Nginx配置-1

    1.绑定nginx到指定cpu [root@nginx conf.d]# vim /apps/nginx/conf/nginx.conf worker_processes 2; worker_cpu_ ...

  10. vs自定义工程宏

    [视图] ---->[其他窗口]----> [属性管理器 ]右键工程---->[添加新项目属性表]打开配置debug/release打开propertysheet找到用户宏即可添加