当前位置:网站首页>Getting started with identityserver4
Getting started with identityserver4
2022-07-24 09:26:00 【It takes time for fish to find water】
IdentifyServer project
IdentityServer4 Is used for ASP.NET Core Of OpenID Connect and OAuth 2.0 frame .
Official website :https://identityserver4.readthedocs.io/en/latest/
establish Asp.net Web Core empty The template project , You can name the base :IdentityServer( The name is optional , Usually take this ), Note that it must be configured Https
quote IdentityServer4
To configure Config, Must be static class
/// <summary> /// IdentityServer4 Configuration class /// </summary> public static class Config { /// <summary> /// Api Range /// </summary> public static IEnumerable<ApiScope> ApiScopes => new[] { new ApiScope() { Name = "simple_api", DisplayName = "Simple_API" } }; public static IEnumerable<Client> Clients => new[] { new Client() { ClientId = "simple_client", ClientSecrets = new List<Secret>() { new Secret("simple_client_secret".Sha256()) }, AllowedGrantTypes = new List<string>(){ GrantType.ClientCredentials}, AllowedScopes = { "simple_api" }// accessible api, There can be multiple }, // Resource owner client new Client() { ClientId = "simple_pass_client", ClientSecrets = new List<Secret>() { new Secret("simple_client_secret".Sha256()) }, AllowedGrantTypes = new List<string>(){ GrantType.ResourceOwnerPassword}, AllowedScopes = { "simple_api" }// accessible api, There can be multiple }, // To configure OICD Redirect new Client() { ClientId = "simple_mvc_client", ClientName = "Simple Mvc Client", ClientSecrets = new List<Secret>() { new Secret("simple_client_secret".Sha256()) }, AllowedGrantTypes = new List<string>(){ GrantType.AuthorizationCode}, // License agreement for authorization code // Login successful jump address ( Pit point : You have to use Https!!!) RedirectUris = { "https://localhost:4001/signin-oidc"}, //mvc Address of the client ,signin-oidc: Endpoint name in standard protocol // Jump address after login PostLogoutRedirectUris = { "https://localhost:4001/signout-callback-oidc"}, AllowedScopes = { IdentityServerConstants.StandardScopes.OpenId, IdentityServerConstants.StandardScopes.Profile, //IdentityResources These two items are defined in , It also needs to be stated here "simple_api" },// accessible api, There can be multiple RequireConsent = true // Whether user's consent is required }, }; // Resource owners (TestUser It's just IdentifyServer4 Provide a test user ) public static List<TestUser> Users = new List<TestUser>() { new TestUser() { SubjectId = "1", Username = "admin", Password = "123" } }; // Define identity resources ( The standard oidc(OpenId Connect)) public static IEnumerable<IdentityResource> IdentityResources = new List<IdentityResource>() { new IdentityResources.OpenId(), new IdentityResources.Profile(),// File information ( nickname , Head portrait ...) }; }- stay
StartUp.csMediumConfigureServicesThe configuration in the method is as follows :
- stay
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddIdentityServer()
.AddDeveloperSigningCredential() // Default generated key ( After operation , Files will be generated in the root directory of the project tempkey.jwk)
.AddInMemoryClients(Config.Clients) // Register client
.AddInMemoryApiScopes(Config.ApiScopes) // register api Scope of visit
.AddTestUsers(Config.Users) // Register the resource owner
.AddInMemoryIdentityResources(Config.IdentityResources); // User's identity resource information ( for example : Show nicknames , Head portrait , Information, etc. )
}
- stay
StartUp.csMediumConfigureConfigure the following code
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.UseRouting();
app.UseIdentityServer();
app.UseAuthorization();
app.UseEndpoints(endpoint =>
{
endpoint.MapDefaultControllerRoute();
});
}
- Run test address :https://localhost:5000/.well-known/openid-configuration
{
"issuer": "https://localhost:5000",
"jwks_uri": "https://localhost:5000/.well-known/openid-configuration/jwks",
"authorization_endpoint": "https://localhost:5000/connect/authorize",
"token_endpoint": "https://localhost:5000/connect/token",
"userinfo_endpoint": "https://localhost:5000/connect/userinfo",
"end_session_endpoint": "https://localhost:5000/connect/endsession",
"check_session_iframe": "https://localhost:5000/connect/checksession",
"revocation_endpoint": "https://localhost:5000/connect/revocation",
"introspection_endpoint": "https://localhost:5000/connect/introspect",
"device_authorization_endpoint": "https://localhost:5000/connect/deviceauthorization",
"frontchannel_logout_supported": true,
"frontchannel_logout_session_supported": true,
"backchannel_logout_supported": true,
"backchannel_logout_session_supported": true,
"scopes_supported": [
"simple_api",
"offline_access"
],
"claims_supported": [],
"grant_types_supported": [
"authorization_code",
"client_credentials",
"refresh_token",
"implicit",
"urn:ietf:params:oauth:grant-type:device_code"
],
"response_types_supported": [
"code",
"token",
"id_token",
"id_token token",
"code id_token",
"code token",
"code id_token token"
],
"response_modes_supported": [
"form_post",
"query",
"fragment"
],
"token_endpoint_auth_methods_supported": [
"client_secret_basic",
"client_secret_post"
],
"id_token_signing_alg_values_supported": [
"RS256"
],
"subject_types_supported": [
"public"
],
"code_challenge_methods_supported": [
"plain",
"S256"
],
"request_parameter_supported": true
}
5. test client : Post request https://localhost:5000/connect/token, Pass request parameters :
test client 1(simple_client)
client_id:simple_client
client_secret:simple_client_secret
grant_type:client_credentials
{
"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjlBMjVFQUVFMjI4RDQyOUQ0QzFEMTc1NjNENzJEQTgzIiwidHlwIjoiYXQrand0In0.eyJuYmYiOjE2MzE4ODg4MzYsImV4cCI6MTYzMTg5MjQzNiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiY2xpZW50X2lkIjoic2ltcGxlX2NsaWVudCIsImp0aSI6IjRBNjI4QUNDODg3OTIxN0YzNzk4QTAwNTUyQjk5OTc4IiwiaWF0IjoxNjMxODg4ODM2LCJzY29wZSI6WyJzaW1wbGVfYXBpIl19.dfWw0h1bpHJy-NAyfOQBEAqthFStndAMPq7nWFAxabKm9A2Wlw4FE9t1bci2DZtgZftb4Uj4GHmibtGyqnTmc4z_OBdZ7llIW3o_LcbiUjMrefohOFGSyRuGVlbzRZb1pbcru8JoNG9k4bFrCLVWvNRUUcUTdVan6ydMkYqNQUg_NJKhKGW9n0HbuoE5nE2yM2eqHHB6IOd6uMYvWzlISfgWNvHlBGtXTGvBkfYjikf6yEz7FuKwuijDeLGPkAbb407ZzFCw-Qo_GV1I9Nzp3IrRe9n9oSSq3_h2plLuL8gNgP8L3Bb82k_LKS-wjBEtm9eLgAh1Mdn6nEL1ezutpg",
"expires_in": 3600,
"token_type": "Bearer",
"scope": "simple_api"
}
among access_token , The structure of this string is jwt Token wrapped by structure , We can put this string into https://jwt.ms Let's decrypt and see what's packed .
{
"alg": "RS256",
"kid": "9A25EAEE228D429D4C1D17563D72DA83",
"typ": "at+jwt"
}.{
"nbf": 1631888836,
"exp": 1631892436,
"iss": "https://localhost:5000",
"client_id": "simple_client",
"jti": "4A628ACC8879217F3798A00552B99978",
"iat": 1631888836,
"scope": [
"simple_api"
]
}.[Signature]
- Test client 2( Resource owner client :simple_pass_client )
client_id:simple_pass_client
client_secret:simple_client_secret
grant_type:password( In fact, that is GrantType.ResourceOwnerPassword)
username:admin( And Config The resources in the class have the same client )
password:123( And Config The resources in the class have the same client )
{
"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjZBQTAwQjMzQTExQzE1M0VGNTZDRkVCNzQ4RTZDQjQxIiwidHlwIjoiYXQrand0In0.eyJuYmYiOjE2MzIxNDk5MDgsImV4cCI6MTYzMjE1MzUwOCwiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NTAwMCIsImNsaWVudF9pZCI6InNpbXBsZV9wYXNzX2NsaWVudCIsInN1YiI6IjEiLCJhdXRoX3RpbWUiOjE2MzIxNDk5MDgsImlkcCI6ImxvY2FsIiwianRpIjoiNjg1QzZDQjBFRjVBQjEzMDhGM0Y1OTlFMDEwMDI3MDciLCJpYXQiOjE2MzIxNDk5MDgsInNjb3BlIjpbInNpbXBsZV9hcGkiXSwiYW1yIjpbInB3ZCJdfQ.tWCsFWnlMinuHvb4UTVK-GxSRUyhSX7GGZPYE05KsZt67K-yriNl1FBI5ZThAWU7qscrCSEBWk1yLd3LR8G3xqEyPkpT4j_xoPTToY7zOAgVHw6wJPV3NxsfzdN07AuYCiPTP9WR9DrWLWy4Iac5GxZ30pcwXNLhPugPRZLG6dUXwry18Dl8jstBHvBQSKGIcrm5HKGeKUxs2aXRg-rl2BmHedRUZK6IjGoABeeSbAUSMfsTOVMdZSXwhdznI6wsjV9YLq3-CerfCIri0BtHVmSJz7hqrq-mg88NK2CZzLEvmKzf73-FprWxdma-6xUEv6E-X4dgOAXt-EZPCSnzWA",
"expires_in": 3600,
"token_type": "Bearer",
"scope": "simple_api"
}
take access_token Put in https://jwt.ms To decrypt and view the results , It can also work with clients 1 Contrast... Contrast
{
"alg": "RS256",
"kid": "6AA00B33A11C153EF56CFEB748E6CB41",
"typ": "at+jwt"
}.{
"nbf": 1632149908,
"exp": 1632153508,
"iss": "https://localhost:5000",
"client_id": "simple_pass_client",
"sub": "1",
"auth_time": 1632149908,
"idp": "local",
"jti": "685C6CB0EF5AB1308F3F599E01002707",
"iat": 1632149908,
"scope": [
"simple_api"
],
"amr": [
"pwd"
]
}.[Signature]
Api project
Create an empty asp.net core webapi
Reference package
Microsoft.AspNetCore.Authentication.JwtUsed for authenticationCreate a new normal Api controller , Add
[Authorize]label[Route("Identity")] [Authorize("MyApiScope")] //MyApiScope This string is the same as Startup Consistent configuration [ApiController] public class IdentityController : ControllerBase { [Authorize] public IActionResult Get() { // User information ( At this time, it is just to simulate the return data , In normal development : Change to the code that accesses the database ) return new JsonResult(from c in User.Claims select new { c.Type, c.Value}); } }modify Startup.cs Class ConfigureServices method code
public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddAuthentication("Bearer").AddJwtBearer("Bearer", p => { //oidc Service address of ( Be sure to use https!!) p.Authority = "https://localhost:5000";// That is to say IdentifyServer Project operation address // Set up jwt Validation parameters for ( By default, this verification is not required ) p.TokenValidationParameters = new TokenValidationParameters { ValidateAudience = false }; }); // Register for authorization services services.AddAuthorization(p => { // Add authorization policy p.AddPolicy("MyApiScope", opt => { // Configure rules for authenticating users , In other words, you must pass identity authentication opt.RequireAuthenticatedUser(); // Identification of api Rules of scope opt.RequireClaim("scope", "simple_api"); }); }); }stay Startup.cs Class Configure Method add authentication method , It must be placed in
app.UseAuthorization()front :app.UseAuthentication();test run :
http://localhost:6000/identity( Be careful ,IdentifyServer That project should be run first ), Remember to use Bearer Form call , That is, add Authorazition:Bearer access_token( Be careful Bearer There's a space after that ),access_token I have got it above
[
{
"type": "nbf",
"value": "1632061080"
},
{
"type": "exp",
"value": "1632064680"
},
{
"type": "iss",
"value": "https://localhost:5000"
},
{
"type": "client_id",
"value": "simple_client"
},
{
"type": "jti",
"value": "BE2D6DCEE4235509666475A049E58DDC"
},
{
"type": "iat",
"value": "1632061080"
},
{
"type": "scope",
"value": "simple_api"
}
]
# Console test client ( Optional )
1. Create a new console application ( During actual development , Use WebMvc)
2. quote `IdentityModel`, It's packed with
3. stay Main Code in :
// Requesting client ( You need to install IdentityModel)
// because IdentityModel Most of them are asynchronous methods , For convenience , We will Main Method is also changed to asynchronous method
// Requesting client ( You need to install IdentityModel)
// because IdentityModel Most of them are asynchronous methods , For convenience , We will Main Method is also changed to asynchronous method
static async Task Main(string[] args)
{
var client = new HttpClient();
// Get discovery file , That is to say https://localhost:5000/.well-known/openid-configuration The result of this address is the discovery of documents
var discoveryDocumentAsync = await client.GetDiscoveryDocumentAsync("https://localhost:5000");
if (discoveryDocumentAsync.IsError)
{
Console.WriteLine(discoveryDocumentAsync.Error);
}
// With the request https://localhost:5000/connect/token This is a meaning
var tokenResponse = await client.RequestClientCredentialsTokenAsync(
new ClientCredentialsTokenRequest()
{
Address = discoveryDocumentAsync.TokenEndpoint,// obtain Token Method address of (token_endpoint Value )
ClientId = "simple_client", // And Config Consistent in class
GrantType = OidcConstants.GrantTypes.ClientCredentials,
ClientSecret = "simple_client_secret" // And Config Consistent in class
}
);
if (tokenResponse.IsError)
{
Console.WriteLine(tokenResponse.Error);
}
// Console.WriteLine(tokenResponse.Json);
// At this time, I have got accessToken, At this time , You can access api 了
var apiClient = new HttpClient {
BaseAddress = new Uri("http://localhost:6000") };
apiClient.SetBearerToken(tokenResponse.AccessToken);// Set access token
var httpResponseMessage = await apiClient.GetAsync("Identity");
var content = await httpResponseMessage.Content.ReadAsStringAsync();
Console.WriteLine(content);
// Test the resource owner client
var resourceTokenResp = await client.RequestPasswordTokenAsync(
new PasswordTokenRequest()
{
Address = discoveryDocumentAsync.TokenEndpoint,// obtain Token Method address of (token_endpoint Value )
ClientId = "simple_pass_client", // And Config Consistent in class
GrantType = OidcConstants.GrantTypes.Password,
ClientSecret = "simple_client_secret", // And Config Consistent in class
UserName = "admin",
Password = "123"
}
);
var apiPassClient = new HttpClient {
BaseAddress = new Uri("http://localhost:6000") };
apiPassClient.SetBearerToken(resourceTokenResp.AccessToken);// Set access token
var httpPassResponseMessage = await apiPassClient.GetAsync("Identity");
var contentPass = await httpPassResponseMessage.Content.ReadAsStringAsync();
Console.WriteLine(contentPass);
Console.ReadKey();
}
add to IdentifyServer project UI
stay IdentifyServer Add below (github Project address :)IdentityServer4.Quickstart.UI
Installation mode :
stay IdentityServer4 Under the project , open cmd, Execute the following command
- First step :
dotnet new -i IdentityServer4.Templates::4.0.1,4.0.1 It's the version number , If you don't write, use the default , This depends on what you install IdentifyServer4 Version of - The second step :
dotnet new is4ui - The results are as follows :
- First step :
F:\workspace\code\ practice \IdentifyServer4\Web.Client\IdentityServer>dotnet new -i IdentityServer4.Templates::4.0.1
Determining items to restore …
Restored C:\Users\Administrator\.templateengine\dotnetcli\v5.0.201\scratch\restore.csproj ( when 9.67 sec).
Templates Short Name Language Tags
---------------------------------------------------- ------------------- ---------- ----------------------
Console Application console [C#],F#,VB Common/Console
Class library classlib [C#],F#,VB Common/Library
WPF Application wpf [C#],VB Common/WPF
WPF Class library wpflib [C#],VB Common/WPF
WPF Custom Control Library wpfcustomcontrollib [C#],VB Common/WPF
WPF User Control Library wpfusercontrollib [C#],VB Common/WPF
Windows Forms App winforms [C#],VB Common/WinForms
Windows Forms Control Library winformscontrollib [C#],VB Common/WinForms
Windows Forms Class Library winformslib [C#],VB Common/WinForms
Worker Service worker [C#],F# Common/Worker/Web
Unit Test Project mstest [C#],F#,VB Test/MSTest
NUnit 3 Test Project nunit [C#],F#,VB Test/NUnit
NUnit 3 Test Item nunit-test [C#],F#,VB Test/NUnit
xUnit Test Project xunit [C#],F#,VB Test/xUnit
Razor Component razorcomponent [C#] Web/ASP.NET
Razor Page page [C#] Web/ASP.NET
MVC ViewImports viewimports [C#] Web/ASP.NET
MVC ViewStart viewstart [C#] Web/ASP.NET
Blazor Server App blazorserver [C#] Web/Blazor
Blazor WebAssembly App blazorwasm [C#] Web/Blazor/WebAssembly
ASP.NET Core Empty web [C#],F# Web/Empty
IdentityServer4 with AdminUI is4admin [C#] Web/IdentityServer4
IdentityServer4 with ASP.NET Core Identity is4aspid [C#] Web/IdentityServer4
IdentityServer4 Empty is4empty [C#] Web/IdentityServer4
IdentityServer4 with Entity Framework Stores is4ef [C#] Web/IdentityServer4
IdentityServer4 with In-Memory Stores and Test Users is4inmem [C#] Web/IdentityServer4
IdentityServer4 Quickstart UI (UI assets only) is4ui [C#] Web/IdentityServer4
ASP.NET Core Web App (Model-View-Controller) mvc [C#],F# Web/MVC
ASP.NET Core Web App webapp [C#] Web/MVC/Razor Pages
ASP.NET Core with Angular angular [C#] Web/MVC/SPA
ASP.NET Core with React.js react [C#] Web/MVC/SPA
ASP.NET Core with React.js and Redux reactredux [C#] Web/MVC/SPA
Razor Class Library razorclasslib [C#] Web/Razor/Library
ASP.NET Core Web API webapi [C#],F# Web/WebAPI
ASP.NET Core gRPC Service grpc [C#] Web/gRPC
dotnet gitignore file gitignore Config
global.json file globaljson Config
NuGet Config nugetconfig Config
Dotnet local tool manifest file tool-manifest Config
Web Config webconfig Config
Solution File sln Solution
Protocol Buffer File proto Web/gRPC
Examples:
dotnet new mvc --auth Individual
dotnet new nunit -f net472
dotnet new --help
dotnet new is4admin --help
F:\workspace\code\ practice \IdentifyServer4\Web.Client\IdentityServer>dotnet new is4ui
The template "IdentityServer4 Quickstart UI (UI assets only)" was created successfully.
F:\workspace\code\ practice \IdentifyServer4\Web.Client\IdentityServer>
here , You go back vs in , You can see IdentityServer There will be more in the project wwwroot,QuickStart,Views These folders , It means success !!
Friendship tips : If dotnet new -i IdentityServer4.Templates::4.0.1 If the command has been executed , There is no need to re execute next time , Just execute dotnet new is4ui Command is enough !!!
- stay Configure Method to register routing and authorization
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.UseRouting();
app.UseIdentityServer();
app.UseAuthorization();
app.UseEndpoints(endpoint =>
{
endpoint.MapDefaultControllerRoute();
});
}
establish Mvc client ( Your text or your system )
This client , In fact, it is the system you want to do .
- Create project Identity.MvcClient project ( You can write this name casually )
- quote
Microsoft.AspNetCore.Authentication.OpenIdConnect - Add... To the controller or view you need to be protected
[Authorize]label - stay startup.cs Class
ConfigureServicesMethod to add oidc(OpenId Connect) authentication
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
services.AddAuthentication(p =>
{
p.DefaultScheme = "Cookies";
p.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", p =>
{
p.Authority = "https://localhost:5000";//IdentityServer The address where the project will run , Be sure to use Https
p.ClientId = "simple_mvc_client";
p.ClientSecret = "simple_client_secret";
p.ResponseType = "code";// Use authorization code form
p.SaveTokens = true; // Save the token in cookie in
p.Scope.Add("simple_api");// In the authentication token , Does it include simple_api
});
}
- stay Configure Method to add authentication middleware , Be careful : Must be on
app.UseAuthorization()front
app.UseAuthentication();
function IdentityServer Project and Mvc project , here , If you access protected resources , Then automatically jump to IdentityServer Project landing page , After successful login , It will immediately return to the protected resource page you just visited , Configuration is successful !!
Exit and log in . Create a method randomly in a controller , Means to log out
// Realize exit page
public IActionResult Logout()
{
// eliminate Cookies, And oidc Information
return SignOut("Cookies", "oidc");
}
To configure EF Core
stay IdentityServer Add references... To the project :
IdentityServer4.EntityFrameworkIdentityServer4.EntityFrameworkimplements the required stores and services using the following DbContexts:- ConfigurationDbContext - used for configuration data such as clients, resources, and scopes
- PersistedGrantDbContext - used for temporary operational data such as authorization codes, and refresh tokens
stay IdentityServer Add references... To the project :
Microsoft.EntityFrameworkCore.SqlServerStartup.cs Middle configuration :
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name; const string connectionString = @"server=.;uid=sa;pwd=123456;database=ids4_oauth;trusted_connection=yes;"; services.AddIdentityServer() .AddConfigurationStore(options => { options.ConfigureDbContext = b => b.UseSqlServer(connectionString, sql => sql.MigrationsAssembly(migrationsAssembly)); }) .AddOperationalStore(options => { options.ConfigureDbContext = b => b.UseSqlServer(connectionString, sql => sql.MigrationsAssembly(migrationsAssembly)); });install install the Entity Framework Core CLI Environmental Science
dotnet tool install --global dotnet-ef --version 3.1.19Reference package :
Microsoft.EntityFrameworkCore.Designstay IdentifyServer In the project folder , Open the command line tool , Execute the data migration command
dotnet ef migrations add InitialIdentityServerPersistedGrantDbMigration -c PersistedGrantDbContext -o Data/Migrations/IdentityServer/PersistedGrantDb
dotnet ef migrations add InitialIdentityServerConfigurationDbMigration -c ConfigurationDbContext -o Data/Migrations/IdentityServer/ConfigurationDb
dotnet ef migrations add InitialApplicationDbMigration -c ApplicationDbContext -o Data/Migrations/IdentityServer/ApplicationDb
perhaps
In the package management console :
add-migration InitApplicationDbMigration -c ApplicationDbContext
update-database InitApplicationDbMigration -c ApplicationDbContext
At this time in ~/Data/Migrations/IdentityServer There will be your newly created code under
6. stay Startup.cs Class , Initialize database ,
public void Configure(IApplicationBuilder app)
{
// this will do the initial DB population
InitializeDatabase(app);
// the rest of the code that was already here
// ...
}
private void InitializeDatabase(IApplicationBuilder app)
{
using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
{
serviceScope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate();
var context = serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
context.Database.Migrate();
if (!context.Clients.Any())
{
foreach (var client in Config.Clients)
{
context.Clients.Add(client.ToEntity());
}
context.SaveChanges();
}
if (!context.IdentityResources.Any())
{
foreach (var resource in Config.IdentityResources)
{
context.IdentityResources.Add(resource.ToEntity());
}
context.SaveChanges();
}
if (!context.ApiScopes.Any())
{
foreach (var resource in Config.ApiScopes)
{
context.ApiScopes.Add(resource.ToEntity());
}
context.SaveChanges();
}
}
}
install IdentityServer4 certificate
https://www.cnblogs.com/chenyishi/p/10922326.html
install OpenSSL Tools , Official website download address :https://slproweb.com/products/Win32OpenSSL.html
stay CMD Execute the following command in
openssl req -newkey rsa:2048 -nodes -keyout cas.clientservice.key -x509 -days 365 -out cas.clientservice.cer
边栏推荐
- 获取所有股票历史行情数据
- [don't bother to strengthen learning] video notes (II) 2. Write a small example of Q learning
- MySQL Basics (I) -- SQL Basics
- Ansible 常用模块介绍
- Wenxin big model raises a new "sail", and the tide of industrial application has arrived
- Huawei wireless device security policy configuration command
- Android system security - 5.2-apk V1 signature introduction
- SDUT compilation principle experimental code
- Firewall off and on command
- Account 1-3
猜你喜欢

Understanding of magnetic parameters in Hall sensors

FreeRTOS - use of software timer

ASI-20220222-Implicit PendingIntent
![[note] what is kernel / user space? Let's start with how the CPU runs the program](/img/b5/0ab4f2841faf3573b4502d2cd09069.png)
[note] what is kernel / user space? Let's start with how the CPU runs the program

Racecar multi-point navigation experiment based on ROS communication mechanism

What is the component customization event we are talking about?

唐宇迪opencv-背景建模

Linked list - 19. Delete the penultimate node of the linked list

Scarcity in Web3: how to become a winner in a decentralized world

Getting started with sorting - insert sorting and Hill sorting
随机推荐
[don't bother to strengthen learning] video notes (IV) 1. What is dqn?
SQL server2012 installation method details [easy to understand]
web安全入门-开源防火墙Pfsense安装配置
财务数字化转型
[translation] integration challenges in microservice architecture using grpc and rest
JS locate Daquan to get the brother, parent and child elements of the node, including robot instances
[don't bother with reinforcement learning] video notes (I) 1. What is reinforcement learning?
[don't bother to strengthen learning] video notes (IV) 2. Dqn realizes maze walking
Hands on deep learning (VII) -- bounding box and anchor box
[assembly language practice] (II). Write a program to calculate the value of expression w=v- (x+y+z-51) (including code and process screenshots)
The difference between classification and regression
Vim: extend the semantic analysis function of YCM for the third-party library of C language
科目1-2
唐宇迪opencv-背景建模
[don't bother with reinforcement learning] video notes (I) 2. Summary of reinforcement learning methods
Account 1-2
Will your NFT disappear? Dfinity provides the best solution for NFT storage
Racecar multi-point navigation experiment based on ROS communication mechanism
Jenkins post build script does not execute
Promise基础总结