当前位置: 首页 > 科技观察

微服务身份服务器的授权与认证4

时间:2023-03-19 00:27:00 科技观察

1.简介IdentityServer4是基于OpenIDConnect和OAuth2.0为ASP.NETCore系列量身打造的认证授权框架。IdentityServer的主要使用场景:1)基于中端认证中心saas系统/pass系统的单点登录或作为统一的认证授权入口(授权方式:授权码方式AuthorizationCode或混合方式hybrid);2)对于API服务与API服务进行固定令牌通信,或者一个业务系统服务集群与其他业务系统服务集群之间,或者一个业务系统集群服务与一个中端服务集群之间,使用的授权方式为clientModeClient凭据;3)用于移动客户端与API服务的通信,授权码方式为自定义授权码。4)用于授权第三方客户端使用平台数据资源,类似于微信、支付宝等用户。主要授权方式为授权码方式AuthorizationCode2。IdentityServer入门demo新建一个.netcore3.1项目,nuget安装IdentityServer4,这里是3.14版本正常情况下,商业业务,Api资源,Client客户端,Identity资源,User等数据存放在数据库中,可以存放token在数据库或redis中。这里作为入门演示,使用内存模式快速搭建。定义一个类,创建API资源,client客户端,我们这里只使用client模式授权,篇幅是个问题,其他授权方式就不一一写了,基本都是publicclassTestConfig{///

///Api资源//////publicstaticIEnumerableGetApiResources(){returnnewList{newApiResource(){Name="myapi",ApiSecrets=newList(){newSecret(){Description="secret",Value="secret".Sha256()}},Scopes=newList(){newScope(){Name="apim"}}},};}//////client//////publicstaticIEnumerableGetClients(){returnnewList{newClient(){ClientId="client",//定义客户端ID//AllowedGrantTypes=newList()//{//GrantTypes.ResourceOwnerPassword.FirstOrDefault(),//GrantType.ClientCredentials,//GrantType.Hybrid//},//必须是单一指定的granttype,可能是内存模型问题。AllowedGrantTypes=GrantTypes.ClientCredentials,//认证密码ClientSecrets={newSecret("secret".Sha256())},AllowedScopes={"apim"},AccessTokenLifetime=360000000},};}publicstaticListGetTestUsers(){returnnewList{newTestUser(){SubjectId="1",Username="test",Password="123456"}};}}注入publicvoidConfigureServices(IServiceCollectionservices){services.AddRazorPages();#regionmemorymodeservices.AddIdentityServer().AddDeveloperSigningCredential()//添加证书加密方法,执行该方法,首先判断tempkey.rsa证书文件是否存在,如果不存在,新建一个tempkey.rsa即可证书文件,如果存在则使用该证书文件。.AddInMemoryApiResources(TestConfig.GetApiResources())//将受保护的Api资源添加到内存中。AddInMemoryClients(TestConfig.GetClients())//将客户端配置添加到内存中。AddTestUsers(TestConfig.GetTestUsers())//添加测试用户。AddDeveloperSigningCredential();#endregion

publicvoidConfigure(IApplicationBuilderapp,IWebHostEnvironmentenv){if(env.IsDevelopment()){app.UseDeveloperExceptionPage();}else{app.UseExceptionHandler("/Error");}app.UseStaticFiles();app.UseRouting();
        //添加中间件      //这个必须在UseRouting和UseEndpoints之间。如果IdentityServer服务端和API要写在一起,//那么这个必须在UseAuthorization和UseAuthentication上面。app.UseIdentityServer();app.UseAuthorization();app.UseEndpoints(endpoints=>{endpoints.MapRazorPages();});} 然后启动服务,使用postman访问identityserver4默认端点地址发现document:使用identityServer4的发现文档中的token_endpoint获取token。已获得令牌。您可以使用发现文档中的introspection_endpoint来验证令牌。如上图所示,我们为client客户端创建了一个访问范围为apim的token。接下来,创建一个受保护的api服务,同样创建一个.netcore3.1服务,并安装nuget包Microsoft.AspNetCore.Authentication.JwtBearer,选择3.14版本,根据.netcore版本在启动类中配置认证授权DI,和添加身份验证和授权中间件:publicclassStartup{//此方法由运行时调用。使用此方法向容器添加服务。//有关如何配置应用程序的详细信息,请访问https://go.microsoft.com/fwlink/?LinkID=398940readonlystringMyAllowSpecificOrigins="_myAllowSpecificOrigins";publicvoidConfigureServices(IServiceCollectionservices){//配置认证服务.AddAuthentication("Bearer").AddJwtBearer(options=>{options.Authority="http://localhost:5000";//授权认证服务options.RequireHttpsMetada刚开始ta=false;options.TokenValidationParameters=newTokenValidationParameters//不验证jwt的aud信息{ValidateAudience=false};});//配置授权策略services.AddAuthorization(options=>{//定义授权策略,名称可以任意Startoptions.AddPolicy("ApiScope",policy=>{policy.RequireAuthenticatedUser();//policy.RequireClaim("scope","apim");//policy要求scope有apim});options.AddPolicy("ApiScope2",policy=>{policy.RequireAuthenticatedUser();//policy.RequireClaim("scope","apim2");});});services.AddSingleton();services.AddCors(options=>{options.AddPolicy(MyAllowSpecificOrigins,builder=>builder.AllowAnyOrigin().WithMethods("GET","POST","HEAD","PUT","DELETE","OPTIONS"));}).AddMvc();services.AddControllers();}//此方法由运行时调用。使用此方法配置HTTP请求管道。publicvoidConfigure(IApplicationBuilderapp,IWebHostEnvironmentenv){if(env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.Use((context,next)=>{context.Request.EnableBuffering();returnnext();});app.UseRouting();//跨域设置app.UseCors(MyAllowSpecificOrigins);//认证中间件(认证必须先于授权)app.UseAuthentication();//授权验证中间件app.UseAuthorization();app.UseEndpoints(endpoints=>{endpoints.MapControllers();});app.UseEndpoints(endpoints=>{endpoints.MapGet("/",asynccontext=>{awaitcontext.Response.WriteAsync("HelloWorld!");});});}} 写2个接口;注意,Authorize标签可以对类或方法生效,根据不同的授权策略来安排需要保护的资源。终于可以使用刚才的token来访问这个API了。如果token错误,就会401。如果授权策略不同,比如mytwo接口被apiScope2策略保护,而apiScope2策略需要apiScope2的scope权限,因为我们刚才获取的token只包含了apim的scope权限,所以访问会返回403权限不足,大家可以试试,试了就不贴了。至此demo结束,大家可以尝试其他方式的token获取3.IdentityServer4数据存储  商业级项目,授权资源需要持久化存储,官方已经提供了基于efcore来维护我们的授权资源和token管理model,context,storageinterface等等,细节我就不写了,推荐参考这篇文章.netcore3.1IdentityServer4(EntityFrameworkCore配置)-陈业新凡的专栏-TNBLOG。下面简单介绍一下基于IdentityServer4EFCore包管理服务的APIResource、Client、Identity资源、Token的相关代码。(provider,builder)=>{builder.UseSqlServer(Configuration.GetSection("Database:ConnectString").Value,sql=>sql.MigrationsAssembly(migrationsAssembly));};}).AddOperationalStore(options=>//注入令牌管理上下文{options.ConfigureDbContext=builder=>builder.UseSqlServer(Configuration.GetSection("Database:ConnectString").Value,sql=>sql.MigrationsAssembly(migrationsAssembly));options.EnableTokenCleanup=true;options.TokenCleanupInterval=3600;}).AddDeveloperSigningCredential();privateConfigurationDbContext_dbContext;私有PersistedGrantDbContext_grantdbContext;//这是身份资源上下文privateIOptions_identityOption;(ConfigurationDbContextdbContext,IOptionsidentityOption,PersistedGrantDbContextgrantdbContext,IMediatormediator){_dbContext=dbContext;_identityOption=身份选项;_grantdbContext=grantdbContext;_mediator=调解员;代码:ViewCode下面有一个修改token过期时间的代码:ViewCode和一个自定义授权方式代码:ViewCodeIdentityServer4也可以扩展端点,但是扩展后发现文档没有显示,但是可以作为http使用,以下代码截图供参考;4.最后  identityServer4要写的东西太多了,整体的把握和理解还是有些复杂。我之前公司的一个通证平台项目是基于认证中心,其他业务系统实现快速集成。我负责授权资源、令牌管理以及IDP授权类型和端点的一些扩展。现在总结成博客,写的不是很详细。希望能给后来者带来一些帮助和参考。