OAuth2.0協議 在開始之前呢,需要我們對一些認證授權協議有一定的瞭解。 OAuth 2.0 的一個簡單解釋 http://www.ruanyifeng.com/blog/2019/04/oauth_design.html 理解 OAuth 2.0 https://www.ruanyifeng. ...
OAuth2.0協議
在開始之前呢,需要我們對一些認證授權協議有一定的瞭解。
OAuth 2.0 的一個簡單解釋
http://www.ruanyifeng.com/blog/2019/04/oauth_design.html
理解 OAuth 2.0
https://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
GitHub OAuth 第三方登錄示例教程
http://www.ruanyifeng.com/blog/2019/04/github-oauth.html
IdentityService4 配置說明
當然,前提是我希望你已經對一些官方示例進行了實踐,如果沒有,下麵鏈接中有中文的案例演示
http://www.identityserver.com.cn/
在官方文檔中我們可以在導航欄看到一些配置項,其實常用的只有Client這一項
https://identityserver4.readthedocs.io/en/latest/index.html
開始操作
先簡單概述一下我們需要做的事情:
1、存儲IdentityService4配置信息
2、存儲用戶數據 (採用ASP.NET Core Identity)
針對上面兩項,官方都有實現,都有針對各自的案例,我們只需要做一個簡單的集合,按需集合進項目中。
建立一個空web項目
.NET Core 版本不做要求 3.1、 5.0、 6.0 都可以實現 ,需要註意的是6.0版本的IdentityService4已經沒有升級了,有一些Nuget包可能是過時的,當出現時,根據提示改為自己需要的版本即可。
我個人喜歡建立MVC,因為方便,中間件都有,懶得一個個引用了
添加所需NuGet包
Startup.cs文件中註冊Identity
// 配置cookie策略 (此配置下方會講解)
builder.Services.Configure<CookiePolicyOptions>(options =>
{
//讓IdentityService4框架在http的情況下可以寫入cookie
options.MinimumSameSitePolicy = Microsoft.AspNetCore.Http.SameSiteMode.Lax;
});
//註冊Identity
//IdentityDB遷移命令
//Add-Migration InitialIAspNetIdentityConfigurationDbMigration -c ApplicationDbContext -o Data/Migrations/AspNetIdentity
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(configuration.GetConnectionString("IdentityDb"), sql => sql.MigrationsAssembly(migrationsAssembly)));
builder.Services.AddIdentity<ApplicationUser, ApplicationRole>(options =>
{
//密碼配置
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireDigit = false;
options.Password.RequiredLength = 6;
options.Password.RequireUppercase = false;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
用的是SqlServer,如若使用MySQL替換Nuget包即可,Oracle有點特殊,自行探索,太麻煩就不說了
ApplicationUser 、ApplicationRole 是我自定義擴展Identity的用戶和角色,這我就不多說了,用過Identity的都知道
Startup.cs文件中註冊IdentityService4
IdentityService4用了兩個DbContext,一個存儲配置信息,一個存儲操作信息
//註冊ID4
builder.Services.AddIdentityServer()
.AddConfigurationStore(options =>
{
//Add-Migration InitialIdentityServerConfigurationDbMigration -c ConfigurationDbContext -o Data/Migrations/IdentityServer/ConfigurationDb
options.ConfigureDbContext = b => b.UseSqlServer(configuration.GetConnectionString("IdentityDb"), sql => sql.MigrationsAssembly(migrationsAssembly));
})
.AddOperationalStore(options =>
{
//Add-Migration InitialIdentityServerPersistedGrantDbMigration -c PersistedGrantDbContext -o Data/Migrations/IdentityServer/PersistedGrantDb
options.ConfigureDbContext = b => b.UseSqlServer(configuration.GetConnectionString("IdentityDb"), sql => sql.MigrationsAssembly(migrationsAssembly));
})
.AddAspNetIdentity<ApplicationUser>()
.AddDeveloperSigningCredential(true);
在授權中間件前,引入IdentityService4中間件
資料庫遷移
此處需要將Identity的Dbcontext上下文,和IdentityService4的兩個DbContext上下文 遷移進資料庫中,遷移命令上面已有,執行即可。
//IdentityDB遷移命令
//Add-Migration InitialIAspNetIdentityConfigurationDbMigration -c ApplicationDbContext -o Data/Migrations/AspNetIdentity
//Add-Migration InitialIdentityServerConfigurationDbMigration -c ConfigurationDbContext -o Data/Migrations/IdentityServer/ConfigurationDb
//Add-Migration InitialIdentityServerPersistedGrantDbMigration -c PersistedGrantDbContext -o Data/Migrations/IdentityServer/PersistedGrantDb
添加自定義所需的頁面(登錄、註冊等)
這些頁面來自官方免費的管理UI、或者Identity,代碼在源碼中,自行拷貝即可
如需其他功能頁面,按需從官方Copy即可
添加測試種子數據
此處代碼太多,自行去源碼查看,講一下原理:
將IdentityService的Client、Scope等配置信息存儲到資料庫中 , 初始化用戶、角色 信息
編譯運行,不報錯,成功!
校驗一下
在當前項目新增一個Api控制器,返回當前Token所包含的聲明信息
註意紅色部分,需要我們添加jwt認證
添加Jwt身份認證
我們在上面註冊服務時,IS4預設使用的是Cookie認證
所以在添加JwtBearer認證
string identityServerUrl = configuration["Perfect:Identity:Url"]; //當前項目地址
//添加jwt認證方案
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
{
options.Authority = identityServerUrl;
options.RequireHttpsMetadata = false;
options.TokenValidationParameters.ValidateAudience = false;
options.TokenValidationParameters.ValidateLifetime = true;
options.TokenValidationParameters.ClockSkew = TimeSpan.Zero;
});
配置swagger認證
先添加一個過濾器
public class SecurityRequirementsOperationFilter : IOperationFilter
{
/// <summary>
/// Add Security Definitions and Requirements
/// https://github.com/domaindrivendev/Swashbuckle.AspNetCore#add-security-definitions-and-requirements
/// </summary>
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
bool hasAuthorize = context.MethodInfo.DeclaringType?.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any() == true || context.MethodInfo.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any();
bool hasAllowAnonymous = context.MethodInfo.DeclaringType?.GetCustomAttributes(true).OfType<AllowAnonymousAttribute>().Any() == true || context.MethodInfo.GetCustomAttributes(true).OfType<AllowAnonymousAttribute>().Any();
if (hasAuthorize && !hasAllowAnonymous)
{
operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" });
operation.Responses.Add("403", new OpenApiResponse { Description = "Forbidden" });
OpenApiSecurityScheme oAuthScheme = new OpenApiSecurityScheme()
{
Reference = new OpenApiReference() { Type = ReferenceType.SecurityScheme, Id = "oauth2" }
};
operation.Security = new List<OpenApiSecurityRequirement>
{
new OpenApiSecurityRequirement
{
[oAuthScheme] =new []{ "Perfect.Api" }
}
};
}
}
}
在Startup中註冊,客戶端ID、和客戶端密鑰 來自步驟 “添加測試種子數據” 中
//configuration["xx"]是來自配置文件的取值
//添加Swagger文檔
services.AddSwaggerGen(c =>
{
c.SwaggerDoc(configuration["Perfect:Swagger:Name"], new OpenApiInfo
{
Title = configuration["Perfect:Swagger:Title"],
Version = configuration["Perfect:Swagger:Version"],
Description = configuration["Perfect:Swagger:Description"],
Contact = new OpenApiContact
{
Name = configuration["Perfect:Swagger:Contact:Name"],
Email = configuration["Perfect:Swagger:Contact:Email"]
}
});
c.OperationFilter<SecurityRequirementsOperationFilter>();
c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.OAuth2,
Flows = new OpenApiOAuthFlows
{
AuthorizationCode = new OpenApiOAuthFlow
{
AuthorizationUrl = new Uri($"{identityServerUrl}/connect/authorize"),
TokenUrl = new Uri($"{identityServerUrl}/connect/token"),
Scopes = new Dictionary<string, string>
{
{ "openapi", "介面訪問許可權" },
}
}
}
});
});
在中間件管道中使用
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint(string.Format("/swagger/{0}/swagger.json", configuration["Perfect:Swagger:Name"]), configuration["Perfect:Swagger:Title"]);
c.OAuthClientId(configuration["Perfect:Swagger:ClientId"]);
c.OAuthClientSecret(configuration["Perfect:Swagger:ClientSecret"]);
c.OAuthAppName(configuration["Perfect:Swagger:AppName"]);
c.OAuthUsePkce();
});
編譯運行,打開swagger頁面
源碼地址:https://github.com/dreamdocker/zerostack
以上教學來自零度課堂,本人只是分享,無其他意義,開會員記得找我哦!
我自是年少,韶華傾負。