简介

  本人做微服务项目也有一段时间了,在微服务中让我感触颇深的就是这个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的端口扫描

    前言 端口扫描是指某些别有用心的人发送一组端口扫描消息,试图以此侵入某台计算机,并了解其提供的计算机网络服务类型(这些网络服务均与端口号相关).端口扫描是计算机解密高手喜欢的一种方式.攻击者可以通过它 ...

  2. 【前端必会】单页应用-你的新朋友wepack

    背景 我们开发的功能可能是简单的,但是实现功能的代码行数却可能成千上万 出于易于维护.安全.服用,我们会根据我们的经验设计我们的代码,拆解成多个独立的功能模块(代码片段.更多的文件) JS的模块规范有 ...

  3. influxDB2.2

    下载安装 下载地址 下载后在解压目录中,输入cmd执行exe文件 浏览器访问localhost:8086 选择快速开始,填写用户信息,组织信息 相关概念 InfluxDB是一个由InfluxData开 ...

  4. PHP全栈开发(一):CentOS 7 配置LAMP

    服务器CentOS7 IP地址:10.28.2.249 进行网络配置 可以使用ip address命令查看当前的网卡状态 两张网卡,一张lo网卡一张ens160网卡 Ens160这个网卡的配置文件为/ ...

  5. 手把手教你使用LabVIEW OpenCV dnn实现图像分类(含源码)

    @ 目录 前言 一.什么是图像分类? 1.图像分类的概念 2.MobileNet简介 二.使用python实现图像分类(py_to_py_ssd_mobilenet.py) 1.获取预训练模型 2.使 ...

  6. 关于for循环当中发生强制类型转换的问题

    Map map1 = new HashMap(); Map map2 = new HashMap(); Map map3 = new HashMap(); List<Map> list = ...

  7. AlexNet-文献阅读笔记

    论文介绍 ImageNet Classification with Deep Convolutional Neural Networks- Alex Krizhevsky, Ilya Sutskeve ...

  8. 记录一次sshd服务启动失败

    记录一次sshd服务启动失败 问题描述: 服务器开机之后发现无法通过远程连接服务器终端,但是服务器并未宕机,于是考虑到sshd服务出现异常 解决思路: 查看服务器sshd服务运行情况 [root@ha ...

  9. 2流高手速成记(之五):Springboot整合Shiro实现安全管理

    废话不多说,咱们直接接上回 上一篇我们讲了如何使用Springboot框架整合Nosql,并于文章最后部分引入了服务端Session的概念 而早在上上一篇中,我们则已经讲到了如何使用Springboo ...

  10. 【神经网络】丢弃法(dropout)

    丢弃法是一种降低过拟合的方法,具体过程是在神经网络传播的过程中,随机"沉默"一些节点.这个行为让模型过度贴合训练集的难度更高. 添加丢弃层后,训练速度明显上升,在同样的轮数下测试集 ...