目录

MongoDB

基本配置

要将 OpenIddict 配置为使用 MongoDB 作为应用程序、授权、范围和令牌的数据库,您需要:

  • 参考OpenIddict.MongoDb

    <PackageReference Include="OpenIddict.MongoDb" Version="3.1.1" />
    
  • 配置 OpenIddict 以使用 MongoDB 存储

    services.AddOpenIddict()
        .AddCore(options =>
        {
            // Note: to use a remote server, call the MongoClient constructor overload
            // that accepts a connection string or an instance of MongoClientSettings.
            options.UseMongoDb()
                   .UseDatabase(new MongoClient().GetDatabase("openiddict"));
        });
    

    或者,您可以将IMongoDatabase实例注册为服务:

    services.AddOpenIddict()
        .AddCore(options =>
        {
            options.UseMongoDb();
        });
    
    // Note: to use a remote server, call the MongoClient constructor overload
    // that accepts a connection string or an instance of MongoClientSettings.
    services.AddSingleton(new MongoClient().GetDatabase("shared-database-instance"));
    
  • 创建索引以提高性能(推荐):为此,您可以使用以下脚本来初始化数据库并创建 OpenIddict 实体使用的索引:

    using System.Threading;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Options;
    using MongoDB.Driver;
    using OpenIddict.MongoDb;
    using OpenIddict.MongoDb.Models;
    
    var services = new ServiceCollection();
    services.AddOpenIddict()
        .AddCore(options => options.UseMongoDb());
    
    services.AddSingleton(new MongoClient("mongodb://localhost:27017").GetDatabase("openiddict"));
    
    var provider = services.BuildServiceProvider();
    var context = provider.GetRequiredService<IOpenIddictMongoDbContext>();
    var options = provider.GetRequiredService<IOptionsMonitor<OpenIddictMongoDbOptions>>().CurrentValue;
    var database = await context.GetDatabaseAsync(CancellationToken.None);
    
    var applications = database.GetCollection<OpenIddictMongoDbApplication>(options.ApplicationsCollectionName);
    
    await applications.Indexes.CreateManyAsync(new[]
    {
        new CreateIndexModel<OpenIddictMongoDbApplication>(
            Builders<OpenIddictMongoDbApplication>.IndexKeys.Ascending(application => application.ClientId),
            new CreateIndexOptions
            {
                Unique = true
            }),
    
        new CreateIndexModel<OpenIddictMongoDbApplication>(
            Builders<OpenIddictMongoDbApplication>.IndexKeys.Ascending(application => application.PostLogoutRedirectUris),
            new CreateIndexOptions
            {
                Background = true
            }),
    
        new CreateIndexModel<OpenIddictMongoDbApplication>(
            Builders<OpenIddictMongoDbApplication>.IndexKeys.Ascending(application => application.RedirectUris),
            new CreateIndexOptions
            {
                Background = true
            })
    });
    
    var authorizations = database.GetCollection<OpenIddictMongoDbAuthorization>(options.AuthorizationsCollectionName);
    
    await authorizations.Indexes.CreateOneAsync(
        new CreateIndexModel<OpenIddictMongoDbAuthorization>(
            Builders<OpenIddictMongoDbAuthorization>.IndexKeys
                .Ascending(authorization => authorization.ApplicationId)
                .Ascending(authorization => authorization.Scopes)
                .Ascending(authorization => authorization.Status)
                .Ascending(authorization => authorization.Subject)
                .Ascending(authorization => authorization.Type),
            new CreateIndexOptions
            {
                Background = true
            }));
    
    var scopes = database.GetCollection<OpenIddictMongoDbScope>(options.ScopesCollectionName);
    
    await scopes.Indexes.CreateOneAsync(new CreateIndexModel<OpenIddictMongoDbScope>(
        Builders<OpenIddictMongoDbScope>.IndexKeys.Ascending(scope => scope.Name),
        new CreateIndexOptions
        {
            Unique = true
        }));
    
    var tokens = database.GetCollection<OpenIddictMongoDbToken>(options.TokensCollectionName);
    
    await tokens.Indexes.CreateManyAsync(new[]
    {
        new CreateIndexModel<OpenIddictMongoDbToken>(
            Builders<OpenIddictMongoDbToken>.IndexKeys.Ascending(token => token.ReferenceId),
            new CreateIndexOptions<OpenIddictMongoDbToken>
            {
                // Note: partial filter expressions are not supported on Azure Cosmos DB.
                // As a workaround, the expression and the unique constraint can be removed.
                PartialFilterExpression = Builders<OpenIddictMongoDbToken>.Filter.Exists(token => token.ReferenceId),
                Unique = true
            }),
    
        new CreateIndexModel<OpenIddictMongoDbToken>(
            Builders<OpenIddictMongoDbToken>.IndexKeys
                .Ascending(token => token.ApplicationId)
                .Ascending(token => token.Status)
                .Ascending(token => token.Subject)
                .Ascending(token => token.Type),
            new CreateIndexOptions
            {
                Background = true
            })
    });
    

高级配置

使用自定义实体

对于需要存储额外数据以及 OpenIddict 使用的属性的应用程序,可以使用自定义实体。为此,您需要:

  • 创建自定义实体

    public class CustomApplication : OpenIddictMongoDbApplication
    {
        public string CustomProperty { get; set; }
    }
    
    public class CustomAuthorization : OpenIddictMongoDbAuthorization
    {
        public string CustomProperty { get; set; }
    }
    
    public class CustomScope : OpenIddictMongoDbScope
    {
        public string CustomProperty { get; set; }
    }
    
    public class CustomToken : OpenIddictMongoDbToken
    {
        public string CustomProperty { get; set; }
    }
    
  • 配置 MongoDb 以使用自定义实体

    services.AddOpenIddict()
        .AddCore(options =>
        {
            options.UseMongoDb()
                   .ReplaceDefaultApplicationEntity<CustomApplication>()
                   .ReplaceDefaultAuthorizationEntity<CustomAuthorization>()
                   .ReplaceDefaultScopeEntity<CustomScope>()
                   .ReplaceDefaultTokenEntity<CustomToken>();
        });
    

使用自定义集合名称

默认情况下,OpenIddict 使用openiddict.[entity name]s模式来确定默认集合名称。需要使用不同集合名称的应用程序可以使用Set*CollectionName()助手:

services.AddOpenIddict()
    .AddCore(options =>
    {
        options.UseMongoDb()
               .SetApplicationsCollectionName("custom-applications-collection")
               .SetAuthorizationsCollectionName("custom-authorizations-collection")
               .SetScopesCollectionName("custom-scopes-collection")
               .SetTokensCollectionName("custom-tokens-collection");
    });