新文章 网摘 文章 随笔 日记

IDENTITYSERVER 3入门工具包:安装IDENTITYSERVER 3,ASP.NET身份和实体框架

设置IdentityServer3的新实例时,需要为每个项目做一些事情。

在为IdentityServer3设置一个简单的启动套件(其中也包含用于用户的IdentityManager用于客户端的admin)时,按照我的步骤,这将是一个小型教程/系列

这是建立新项目时快速开始使用IdentityServer的起点。这也可用作入门和从头开始设置IdentityServer 3的指南,以及了解所有丢失部分的指南。

设置项目

我们将从创建一个空的ASP.NET Web应用程序开始,它将作为项目的宿主应用程序。

1个新项目

由于我们不需要该项目的任何默认模板,因此我们可以选择创建一个Empty项目

2个新项目空白

接下来,是使用https设置开发环境。为此,我们需要打开项目的属性并将Web-> Project url设置为https:// url。

3个项目的网址

切记单击“创建虚拟目录”按钮以启用URL。

4个项目的网址

为了能够处理内置资产,我们需要在Web.config文件中启用设置。

<configuration>
  ...
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
  </system.webServer>
</configuration>

如果启动IdentityServer时遇到的欢迎页面没有任何有效的CSS,JS或图像,则您可能会错过“ RunAllManagedModulesForAllRequests”设置。

现在我们准备继续并开始安装软件包。

设置IDENTITYSERVER 3核心功能

安装基本软件包

完成项目设置后,我们将安装一些软件包,IdentityServer3安装IdentityServer的基础,IdentityServer3.AspNetIdentity以支持ASP.NET Identity,IdentityServer3.EntityFramework,以支持使用EntityFramework从SQL Server获得持久数据,Microsoft.AspNet.Identity.EntityFramework创建ASP.NET身份实体,Microsoft.Owin能够在启动时设置IdentityServer

Install-Package IdentityServer3 
Install-Package IdentityServer3.AspNetIdentity 
Install-Package IdentityServer3.EntityFramework
Install-Package Microsoft.Owin.Host.SystemWeb
Install-Package Microsoft.AspNet.Identity.EntityFramework

如果您希望服务器是自托管的,则可以创建一个控制台应用程序并安装包Microsoft.Owin.Host.HttpListner和Microsoft.Owin.Hosting而不是Microsoft.Owin.Host.SystemWeb

设置一些先决条件

常数

首先,我们将设置Constants.cs,该文件将用于在整个过程中包含一些常量。在这里,我们为将在入门工具包以及IdentityServer的核心端点中使用的连接字符串定义名称。

// <copyright file="Constants.cs">
//    2017 - Johan Boström
// </copyright>
 
namespace IdentityServer3.StarterKit
{
  public static class Constants
  {
    public const string ConnectionStringName = "AspId";
 
    public class Routes
    {
        public const string Core = "/ids";
        public const string IdMgr = "/idm";
        public const string IdAdm = "/ida";
    }
  }
}

证书

我们还需要有一个可以用来对令牌进行签名的证书。出于测试目的,我从IdentityServers github下载了测试证书,可以在这里找到。然后将证书添加到项目中,并将构建操作更改为“嵌入式资源”。

现在,我们需要能够读取证书,这可以通过创建类证书并以流形式读取文件,然后创建X509Certificate2来完成。

// <copyright file="Certificate.cs">
//    2017 - Johan Boström
// </copyright>

using System.IO;
using System.Security.Cryptography.X509Certificates;
 
namespace IdentityServer3.StarterKit.Config
{
    public static class Certificate
    {
        public static X509Certificate2 Get()
        {
            var assembly = typeof(Certificate).Assembly;
            using (var stream = assembly.GetManifestResourceStream("IdentityServer3.StarterKit.Config.idsrv3test.pfx"))
            // Should be the path to the embeded certificate
            {
                return new X509Certificate2(ReadStream(stream), "idsrv3test");
            }
        }
        
        private static byte[] ReadStream(Stream input)
        {
            var buffer = new byte[16 * 1024];
            using (var ms = new MemoryStream())
            {
                int read;
                while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
                    ms.Write(buffer, 0, read);
                return ms.ToArray();
            }
        }
    }
}

数据库模型

现在,我们可以开始设置模型,以便在将数据存储到数据库时供用户使用,该模型可用于在条目上保留额外的信息。在用户上,我们将添加一个名字和一个姓氏以便以后输入。除此之外,由于该模型将继承IdentityUser的所有需求,因此现在不需要更多信息。

// <copyright file="User.cs">
//    2017 - Johan Boström
// </copyright>
 
using Microsoft.AspNet.Identity.EntityFramework;
 
namespace IdentityServer3.StarterKit.Models
{
  public class User : IdentityUser
  {
    public string FirstName { get; set; }
    public string LastName { get; set; }
  }
}

语境

接下来是设置数据库上下文,这是通过创建一个类并从IdentityDbContext继承并使用我们创建的用户模型以及一些直接来自Microsoft.AspNet.Identity.EntityFramework的模型来完成的。

// <copyright file="Context.cs">
//    2017 - Johan Boström
// </copyright>

using IdentityServer3.StarterKit.Models;
using Microsoft.AspNet.Identity.EntityFramework;

namespace IdentityServer3.StarterKit.Db
{
    public class Context : IdentityDbContext<User, IdentityRole, string,IdentityUserLogin, IdentityUserRole, IdentityUserClaim>
    {
        public Context(string connString)
            : base(connString)
        {
        }
    }
}

专卖店

现在已经有了上下文,我们可以创建一个UserStoreRoleStore,系统可以使用它们来创建,查找,更新和删除用户和商店。我们将通过继承Microsoft.AspNet.Identity.EntityFramework中的商店来创建它们

// <copyright file="UserStore.cs">
//    2017 - Johan Boström
// </copyright>
 
using IdentityServer3.StarterKit.Db;
using IdentityServer3.StarterKit.Models;
using Microsoft.AspNet.Identity.EntityFramework;
 
namespace IdentityServer3.StarterKit.Stores
{
  public class UserStore : UserStore<User, IdentityRole, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>
  {
    public UserStore(Context context)
        : base(context)
    {
    }
  }
}


// <copyright file="RoleStore.cs">
//    2017 - Johan Boström
// </copyright>
 
using IdentityServer3.StarterKit.Db;
using Microsoft.AspNet.Identity.EntityFramework;
 
namespace IdentityServer3.StarterKit.Stores
{
  public class RoleStore : RoleStore<IdentityRole>
  {
    public RoleStore(Context context)
        : base(context)
    {
    }
  }
}

管理人员

// <copyright file="UserManager.cs">
//    2017 - Johan Boström
// </copyright>
 
using IdentityServer3.StarterKit.Factories;
using IdentityServer3.StarterKit.Models;
using IdentityServer3.StarterKit.Stores;
using Microsoft.AspNet.Identity;
 
namespace IdentityServer3.StarterKit.Managers
{
  public class UserManager : UserManager<User, string>
  {
    public UserManager(UserStore store)
        : base(store)
    {
        ClaimsIdentityFactory = new ClaimsFactory();
    }
  }
}


// <copyright file="RoleManager.cs">
//    2017 - Johan Boström
// </copyright>
 
using IdentityServer3.StarterKit.Stores;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;

namespace IdentityServer3.StarterKit.Managers
{
    public class RoleManager : RoleManager<IdentityRole>
    {
        public RoleManager(RoleStore store)
            : base(store)
        {
        }
    }
}

创建CLAIMSIDENTITY

AspNet身份使用ClaimsIdentity作为身份类型,并且为了能够在需要设置ClaimsIdentityFactory之前,从创建的用户模型中创建此实例。这样,我们将能够提取添加到用户模型中的名字和姓氏,并将其添加为可能的声明。

// <copyright file="ClaimsIdentityFactory.cs">
//    2017 - Johan Boström
// </copyright>
 
using System.Security.Claims;
using System.Threading.Tasks;
using IdentityServer3.StarterKit.Models;
using Microsoft.AspNet.Identity;
 
namespace IdentityServer3.StarterKit.Factories
{
    public class ClaimsIdentityFactory : ClaimsIdentityFactory<User, string>
    {
        public ClaimsIdentityFactory()
        {
            UserIdClaimType = Core.Constants.ClaimTypes.Subject;
            UserNameClaimType = Core.Constants.ClaimTypes.PreferredUserName;
            RoleClaimType = Core.Constants.ClaimTypes.Role;
        }

        public override async Task<ClaimsIdentity> CreateAsync(UserManager<User, string> manager, User user, string authenticationType)
        {
            var ci = await base.CreateAsync(manager, user, authenticationType);
 
            if (!string.IsNullOrWhiteSpace(user.FirstName))
                ci.AddClaim(new Claim("given_name", user.FirstName));

            if (!string.IsNullOrWhiteSpace(user.LastName))
                ci.AddClaim(new Claim("family_name", user.LastName));

            return ci;
        }
    }
}

用户服务

现在我们只需要一个AspNetIdentityUserService实现,该实现我们之前安装IdentityServer3.AspNetIdentity包的一部分,因此它将使用新的用户模型。这样我们就可以开始将所有丢失的部分放在一起。

// <copyright file="UserService.cs">
//    2017 - Johan Boström
// </copyright>

using IdentityServer3.AspNetIdentity;
using IdentityServer3.StarterKit.Managers;
using IdentityServer3.StarterKit.Models;
 
namespace IdentityServer3.StarterKit.Services
{
    public class UserService : AspNetIdentityUserService<User, string>
    {
        public UserService(UserManager userManager)
            : base(userManager)
        {
        }
    }
}

配置IDENTITYSERVER

设置默认范围,用户和客户端

首先,我们可以设置一些值,这些值可以用作我们可以操作和添加的数据的起点。仅当表中没有其他实体时,才会添加以下这些值。对于我决定将默认范围添加到数据库的范围,我添加了一个用户,以便我们有一个用户可以登录并尝试使用该系统。我还添加了一个客户端,可用于在入门套件系列的后续部分中进行构建。

// <copyright file="DefaultSetup.cs">
//    2017 - Johan Boström
// </copyright>
 
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using IdentityServer3.Core.Models;
using IdentityServer3.EntityFramework;
using IdentityServer3.StarterKit.Db;
using IdentityServer3.StarterKit.Managers;
using IdentityServer3.StarterKit.Models;
using IdentityServer3.StarterKit.Stores;
using Microsoft.AspNet.Identity;
 
namespace IdentityServer3.StarterKit.Config
{
    public class DefaultSetup
    {
        public static void Configure(EntityFrameworkServiceOptions options)
        {
            using (var db = new ScopeConfigurationDbContext(options.ConnectionString, options.Schema))
            {
                if (!db.Scopes.Any())
                {
                    foreach (var s in StandardScopes.All)
                    {
                        var e = s.ToEntity();
                        db.Scopes.Add(e);
                    }
 
                    foreach (var s in StandardScopes.AllAlwaysInclude)
                    {
                        var e = s.ToEntity();
                        db.Scopes.Add(e);
                    }
 
                    db.SaveChanges();
                }
            }
 
            using (var db = new Context(options.ConnectionString))
            {
                if (!db.Users.Any())
                {
                    using (var userManager = new UserManager(new UserStore(db)))
                    {
                        var defaultUserPassword = "skywalker"; // Must be atleast 6 characters
                        var user = new User
                        {
                            UserName = "administrator",
                            FirstName = "Luke",
                            LastName = "Skywalker",
                            Email = "luke.skywalker@email.com",
                            EmailConfirmed = true
                        };
                        userManager.Create(user, defaultUserPassword);
                        userManager.AddClaim(user.Id,
                        new Claim(Core.Constants.ClaimTypes.WebSite, "https://www.johanbostrom.se/"));
                    }
 
                    db.SaveChanges();
                }
            }
 
            using (var db = new ClientConfigurationDbContext(options.ConnectionString, options.Schema))
            {
                if (!db.Clients.Any())
                {
                    var defaultHybridClient = new Client
                    {
                        ClientName = "Default Hybrid Client",
                        ClientId = "default.hybrid",
                        Flow = Flows.Hybrid,
                        ClientSecrets = new List<Secret>
                        {
                            new Secret("default.hybrid.password".Sha256())
                        },
                        AllowedScopes = new List<string>
                        {
                            Core.Constants.StandardScopes.OpenId,
                            Core.Constants.StandardScopes.Profile,
                            Core.Constants.StandardScopes.Email,
                            Core.Constants.StandardScopes.Roles,
                            Core.Constants.StandardScopes.Address,
                            Core.Constants.StandardScopes.Phone,
                            Core.Constants.StandardScopes.OfflineAccess
                        },
                        ClientUri = "https://localhost:44300/",
                        RequireConsent = false,
                        AccessTokenType = AccessTokenType.Reference,
                        RedirectUris = new List<string>(),
                        PostLogoutRedirectUris = new List<string>
                        {
                            "https://localhost:44300/"
                        },
                        LogoutSessionRequired = true
                    };
 
                    db.Clients.Add(defaultHybridClient.ToEntity());
                    db.SaveChanges();
                }
            }
        }
    }
}

映射,注册和配置

现在剩下的就是将所有内容放在一起并映射IdentityServer核心。我决定为IAppBuilder创建一个带有证书的扩展。在这里,我们根据设置的常量配置EntityFramework(EF),创建IdentityServerServiceFactory并根据EF配置注册服务。我们还注册我们创建UserService服务并运行默认配置设置。最后,它运行带有工厂和一些调试参数UseIdentityServer扩展。

// <copyright file="AppBuilderExtensions.cs">
//    2017 - Johan Boström
// </copyright>
 
using System.Security.Cryptography.X509Certificates;
using IdentityServer3.Core.Configuration;
using IdentityServer3.Core.Services;
using IdentityServer3.EntityFramework;
using IdentityServer3.StarterKit.Config;
using IdentityServer3.StarterKit.Db;
using IdentityServer3.StarterKit.Managers;
using IdentityServer3.StarterKit.Services;
using IdentityServer3.StarterKit.Stores;
using Owin;
 
namespace IdentityServer3.StarterKit.Extensions
{
    public static class AppBuilderExtensions
    {
        public static IAppBuilder MapCore(this IAppBuilder app, X509Certificate2 signingCertificate)
        {
            app.Map(Constants.Routes.Core, coreApp =>
            {
                var efConfig = new EntityFrameworkServiceOptions
                {
                    ConnectionString = Constants.ConnectionStringName
                };
 
                var factory = new IdentityServerServiceFactory();
 
                factory.RegisterConfigurationServices(efConfig);
                factory.RegisterOperationalServices(efConfig);
                factory.RegisterClientStore(efConfig);
                factory.RegisterScopeStore(efConfig);

                factory.Register(new Registration<UserManager>());
                factory.Register(new Registration<UserStore>());
                factory.Register(new Registration<Context>(resolver => new Context(Constants.ConnectionStringName)));

                factory.UserService = new Registration<IUserService, UserService>();

            DefaultSetup.Configure(efConfig);
 
                coreApp.UseIdentityServer(new IdentityServerOptions
                {
                    Factory = factory,
                    SigningCertificate = signingCertificate,
                    SiteName = "IdentityServer3 Starter Kit",
                    LoggingOptions = new LoggingOptions
                    {
                        EnableKatanaLogging = true
                    },
                    EventsOptions = new EventsOptions
                    {
                        RaiseFailureEvents = true,
                        RaiseInformationEvents = true,
                        RaiseSuccessEvents = true,
                        RaiseErrorEvents = true
                    }
                });
            });
 
            return app;
        }
    }
}

最后一个难题是Owin创业公司。我创建了一个名为Startup.cs的文件,并为IAppBuilder运行了核心映射扩展。

// <copyright file="Startup.cs">
//    2017 - Johan Boström
// </copyright>
 
using IdentityServer3.StarterKit;
using IdentityServer3.StarterKit.Config;
using IdentityServer3.StarterKit.Extensions;
using Microsoft.Owin;
using Owin;
 
[assembly: OwinStartup(typeof(Startup))]
 
namespace IdentityServer3.StarterKit
{
  public class Startup
  {
    public void Configuration(IAppBuilder app)
    {
      var certificate = Certificate.Get();
      app.MapCore(certificate);
    }
  }
}

做完了!

好吧,最后一切都应该做好。运行时,我们现在应该能够访问https:// localhost:44300 / ids并看到欢迎屏幕。我们还应该能够单击权限页面的链接,然后使用我们的管理员用户登录。

所有代码示例和完整的入门工具包项目都可以在我的GitHub页面上找到,并且由于这是系列文章的一部分,因此该代码将通过后续部分的更多功能不断进行更新。

 

https://johanbostrom.se/blog/identityserver-3-starter-kit-part-1-installing-identityserver-3-aspnet-identity-and-entity-framework/

posted @ 2020-06-12 10:56  岭南春  阅读(202)  评论(0编辑  收藏  举报