IdentityServer4 + SignalR Core +RabbitMQ 構建web即時通訊(一)


IdentityServer4 + SignalR Core +RabbitMQ 構建web即時通訊


 

前言

 

.net core 2.1已經正式發布了,signalr core1.0隨之發布,是時候寫個demo了,這里帶大家復習了下知識鏈,構建一個web即時聊天室,整個應用構建思路如下: 
1.使用IdentityServer4作為獨立的用戶中心與認證中心,采用password授權模式給客戶端提供token, 
2.使用RabbitMQ作為消息處理器,客戶端發送消息到服務端,服務器並不直接響應該消息,而是發送到消息隊列,再由消息處理器獲取消息並發送到客戶端,提高服務端的處理能力, 
3.數據庫使用postgresql,本來准備使用mysql的,不過截止發稿時,EF Core2.1發布后,mysql的使用Code First存在bug還未解決, 
4.使用Docker構建RabbitMQ,postgresql應用,

5. 前后端分離。

地址:https://github.com/280780363/signalrdemo.git


Docker構建基礎應用RabbitMQ,postgresql 
環境:虛擬機centos 7.0,docker 
xshell連接到centos。 
1,啟動RabbitMQ容器,官方鏡像地址,設置默認用戶admin,密碼123123,具體環境變量這些的設置可以參考官方文檔: 
docker run -d --hostname myrabbit --name myrabbit -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=123123 -p 15672:15672 -p 5672:5672 -p 25672:25672 -p 61613:61613 -p 1883:1883 --restart=always rabbitmq:management
2.啟動postgresql,官方鏡像地址,設置默認用戶gucao,密碼123123,這里啟動時設置的用戶是屬於超級管理員,掛載數據卷~/docker/postgresql/pgdata目錄作為數據存儲目錄,--privileged設置容器擁有root權限進行文件讀寫: 
docker run --restart=always --privileged --name mypostgresql -e POSTGRES_PASSWORD=123123 -e POSTGRES_USER=gucao -v ~/docker/postgresql/pgdata:/var/lib/postgresql/data/ -d -p 5432:5432 postgres
成功啟動后: 

 

端口號都映射為默認端口。psotgresql默認端口號5432,RabbitMQ用的到端口號比較多,15672是ui管理的端口號。我的虛擬機IP是192.168.1.107。瀏覽器打開地址:192.168.1.107:15672:

能看到這個登錄頁面就說明一切ok了。輸入容器啟動時設置的用戶名密碼。登錄后可以查看當前的一些隊列信息。

使用Navicat連接數據庫,也沒有問題:

就這么簡單的2個命令就啟動了2個應用,如果自己下載安裝包來安裝,那真是夠折騰人的,還得考慮各種各樣的環境,不得不說docker真是一個偉大的工具。

 


  IdentityServer4 用戶中心

 

 關於IdentityServer4的具體各種使用這里不會贅述,大家可以多參考以下資料: 
官方文檔 
曉晨的博客

我們這里集成AspNetCore Identity提供用戶管理,客戶端(client),資源(ApiResource,IdentityResource)等配置資料都使用數據庫存儲。

需要用到的庫:

1.IdentityServer4;

2.IdentityServer4.AspNetIdentity ,IdentityServer4集成AspNetCore Identity用到的庫;

3.IdentityServer4.EntityFramework,IdentityServer4使用EF作為數據存儲用到的庫;

4.Npgsql.EntityFrameworkCore.PostgreSQL,postgresql ef驅動庫;

5.Microsoft.EntityFrameworkCore.Tools,Ef Code First工具庫。

好吧,啰嗦一點,

1.創建空的.net core web項目 Demo.Identity,nuget安裝以上用到的庫;

2.創建appsettings.json配置文件,增加數據庫連接配置,文件名不能錯,ConnectionStrings不能錯,這是默認的約定

{
  "ConnectionStrings": {
    "chat": "server=192.168.1.107;user id=gucao;password=123123;persistsecurityinfo=True;database=signalrdemo;"
  }
}

3.增加Data文件夾,存放用戶實體,DbContext,種子數據文件類,這里我們使用guid作為主鍵,這里主要是AspNetCore Identity的類

DemoUser繼承自IdentityUser<Guid>,增加一個頭像屬性

    public class DemoUser : IdentityUser<Guid>
    {
        public string Avatar { get; set; }
    }

因為默認是string類型的主鍵,要更改主鍵類型,需要同時建一個Role類,也設置為guid主鍵,DemoRole:

    public class DemoRole : IdentityRole<Guid>
    {
    }

DemoDbContext

    public class DemoDbContext : IdentityDbContext<DemoUser, DemoRole, Guid>
    {
        public DemoDbContext(DbContextOptions<DemoDbContext> options) : base(options)
        {
        }
    }

SeedData就用來提供基本的數據了,這里先設置3個用戶,要聊天總不能一個人聊得開心是吧

        public static List<DemoUser> Users()
        {
            return new List<DemoUser>{
                new DemoUser
                {
                    UserName = "laowang",
                    Email = "520@qq.com",
                    Id = Guid.NewGuid(),
                    EmailConfirmed = true,
                    TwoFactorEnabled = false,
                    Avatar = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1528131041794&di=78ae71a3573dc86bc010e301005fea53&imgtype=0&src=http%3A%2F%2Fpic2.orsoon.com%2F2017%2F0309%2F20170309032925886.png"
                },
                new DemoUser
                {
                    UserName = "zhangsan",
                    Email = "521@qq.com",
                    Id = Guid.NewGuid(),
                    EmailConfirmed = true,
                    TwoFactorEnabled = false,
                    Avatar = "http://pic20.photophoto.cn/20110804/0010023712739303_b.jpg"
                },
                new DemoUser
                {
                    UserName = "lisi",
                    Email = "521@qq.com",
                    Id = Guid.NewGuid(),
                    EmailConfirmed = true,
                    TwoFactorEnabled = false,
                    Avatar = "http://p1.qzone.la/upload/0/14vy5x96.jpg"
                }
            };
        }

4.好了 下面開始配置StartUp中的服務,這里我就直接貼代碼了

        public void ConfigureServices(IServiceCollection services)
        {
            // 配置AspNetCore Identity 的DbContext服務
            services.AddDbContext<DemoDbContext>(r =>
            {
                r.UseNpgsql(configuration.GetConnectionString("chat"), options =>
                {
                    // 配置遷移時程序集
                    options.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
                });
            });

            // 配置AspNetCore Identity服務用戶密碼的驗證規則
            services.AddIdentity<DemoUser, DemoRole>(options =>
            {
                options.Password.RequireDigit = false;
                options.Password.RequiredLength = 6;
                options.Password.RequireLowercase = false;
                options.Password.RequireUppercase = false;
                options.Password.RequireNonAlphanumeric = false;

            })
            // 告訴AspNetCore Identity 使用DemoDbContext為數據庫上下文
            .AddEntityFrameworkStores<DemoDbContext>()
            .AddDefaultTokenProviders();

            // 配置ids4服務
            services.AddIdentityServer()
                .AddDeveloperSigningCredential()
                // ids4使用AspNetCore Identity為用戶認證
                .AddAspNetIdentity<DemoUser>()
                // 使用數據庫來存儲客戶端Clients ApiResource IdentityResource
                .AddConfigurationStore(options =>
                {
                    options.ConfigureDbContext = builder =>
                    {
                        builder.UseNpgsql(configuration.GetConnectionString("chat"), sql =>
                        {
                            sql.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
                        });
                    };
                })
                // 使用數據庫存儲授權操作相關操作,數據庫表PersistedGrants
                .AddOperationalStore(options =>
                {
                    options.ConfigureDbContext = builder =>
                    {
                        builder.UseNpgsql(configuration.GetConnectionString("chat"), sql =>
                        {
                            sql.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
                        });
                    };
                })
                // ids4使用自定義的用戶檔案服務
                .Services.AddTransient<IProfileService, ProfileService>();

            // 配置跨域,允許所有
            services.AddCors(r =>
            {
                r.AddPolicy("all", policy =>
                {
                    policy
                    .AllowAnyOrigin()
                    .AllowAnyHeader()
                    .AllowAnyMethod()
                    .AllowCredentials()
                    ;
                });
            });
        }
View Code

 這里有一句Services.AddTransient<IProfileService, ProfileService>(),什么意思呢?我希望在前端通過請求token時,token中自帶有用戶基本信息:用戶名,頭像等等,通過這個類配置ids4發布token時帶上這些用戶信息;

    public class ProfileService : IProfileService
    {
        UserManager<DemoUser> userManager;
        // 注入AspNetCore Identity的用戶管理類
        public ProfileService(UserManager<DemoUser> userManager)
        {
            this.userManager = userManager;
        }
        public async Task GetProfileDataAsync(ProfileDataRequestContext context)
        {
            var claims = context.Subject.Claims.ToList();
            // sub屬性就是用戶id
            var userId = claims.First(r => r.Type == "sub");
            // 查找用戶
            var user = await userManager.FindByIdAsync(userId.Value);
            claims.Add(new System.Security.Claims.Claim("username", user.UserName));
            claims.Add(new System.Security.Claims.Claim("email", user.Email));
            claims.Add(new System.Security.Claims.Claim("avatar", user.Avatar));
            // 這里是設置token包含的用戶屬性claim
            context.IssuedClaims = claims;
        }

        public async Task IsActiveAsync(IsActiveContext context)
        {
            context.IsActive = true;
            await Task.CompletedTask;
        }
    }
View Code

Configure

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseCors("all");
            app.UseIdentityServer();
        }
View Code

5.可以開始生成遷移代碼了,這里有3個DbContext類需要生成遷移:DemoDbContext,ConfiguraionDbContext(ids4 配置數據上下文),PersistedGrantDbContext(ids4授權操作數據上下文)

Add-Migration init -Context DemoDbContext -OutputDir Migrations/IdentityDbMigrations

Add-Migration init -Context ConfigurationDbContext -OutputDir Migrations/ConfigurationDbMigrations

Add-Migration init -Context PersistedGrantDbContext -OutputDir Migrations/PersistedGrantDbMigrations

 

好了,篇幅有點長了,先到這。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM