电商设计网站素材,能赚钱的网站,学校网站建设是什么意思,企业网站 备案 网站名称迎周一#xff0c;腊月十九#xff0c;小年倒计时新年还有两周时间就要到了#xff0c;学习可不能停#xff0c;这几天一直在加班调休#xff0c;周末也如此#xff0c;不过也是趁着半夜凌晨的时间#xff0c;继续迁移我的项目到IdentityServer4统一认证授权中心Blog.Id… 迎周一腊月十九小年倒计时新年还有两周时间就要到了学习可不能停这几天一直在加班调休周末也如此不过也是趁着半夜凌晨的时间继续迁移我的项目到IdentityServer4统一认证授权中心Blog.IdentityServer上也是基本统一了目前进度如下01、前后端分离全家桶已经完成升级Blog.Core为apiBlog.Admin为后台管理Blog.Vue为前台信息展示已经全部搞定具体的代码查看指定Github的分支即可分支名基本都是Is4Ids4等字样02、Nuxt.tBug项目目前正在升级中其实和Vue的前后端分离是一样的都是使用的同一个组件框架oidc-client这里就不多说了如果真的差别大我就单写一篇文章否则直接看我的代码就行03、ChristDDD MVC项目已经完成迁移就是今天本文讲解的。04、WPF项目在进度种到时候简单写个小Demo就行我会在我的视频中给大家讲解预计春节后出来。上边共涉及到了我开源的六个项目三个后端三个前端想想这一年也是够可以了但是在迁移的IdentityServer4中只用到了常用的两种模式Implicit和Code模式其实一般我们web开发掌握四种就行除了这两个还有Hybrid和Client其他的如果没有精力可以放一放那下边我们就快速的说一下如何将MVC项目迁移到Ids4上。这里就简单的说一下操作过程不会讲解原理原理我会在视频教程中详细说到。Idp项目如何配置具体的原型图运行原理等我视频吧直接看代码这里要说一下如果你是第一次开发学习我建议尽量使用内存模式这样会很好的调试如果直接生成到数据库的话可能有时候修改了一个配置还需要重新生成数据库这个有些浪费时间。在我们的Config.cs中新建一个Client用来应对我们的MVC客户端// interactive ASP.NET Core MVC client
new Client
{ClientId chrisdddmvc,ClientNameChris DDD MVC项目,ClientSecrets { new Secret(secret.Sha256()) },AllowedGrantTypes GrantTypes.Code,RequireConsent false,RequirePkce true,AlwaysIncludeUserClaimsInIdTokentrue,//将用户所有的claims包含在IdToken内// 登录回调RedirectUris { http://ddd.neters.club/signin-oidc },// 登出回调地址PostLogoutRedirectUris { http://ddd.neters.club/signout-callback-oidc },// 注意这些scope一定是上边已经定义好的资源AllowedScopes new Liststring{IdentityServerConstants.StandardScopes.OpenId,IdentityServerConstants.StandardScopes.Profile,IdentityServerConstants.StandardScopes.Email,roles,rolename,}
}
这里就强调两点就是配置一下回调地址然后就是AlwaysIncludeUserClaimsInIdToken要设置为true以方便我们后边要从claims声明中获取返回的值。当然最后还有一个知识点就是scope中如果想要自定义的话需要先在claims中注册添加然后在GetIdentityResources中配置 // scopes define the resources in your systempublic static IEnumerableIdentityResource GetIdentityResources(){return new ListIdentityResource{new IdentityResources.OpenId(),new IdentityResources.Profile(),new IdentityResources.Email(),new IdentityResource(roles, 角色, new Liststring { JwtClaimTypes.Role }),new IdentityResource(rolename, 角色名, new Liststring { rolename }),};}
这里配置就是很简单的咱们继续看看如何在MVC中配置。ChristDDD如何配置如果你之前看过或者用到了我的DDD项目会发现其实本来是用Identity写的这次我们迁移到Ids4后需要做一些变化具体的直接下载我的Ids4分支就行了修改的内容比较多。首先我们把响应的认证服务给抽出来单独封装上边的是Ids4的下边的是普通的Identity的然后注入服务 // IdentityServer4 注入services.AddId4OidcSetup();
那我们直接看看服务是如何设置的 private static readonly string config https://ids.neters.club;public static void AddId4OidcSetup(this IServiceCollection services){if (services null) throw new ArgumentNullException(nameof(services));//关闭默认映射否则它可能修改从授权服务返回的各种claim属性JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();//添加认证服务并设置其有关选项services.AddAuthentication(options {// 客户端应用设置使用Cookies进行认证options.DefaultScheme CookieAuthenticationDefaults.AuthenticationScheme;// identityserver4设置使用oidc进行认证options.DefaultChallengeScheme OpenIdConnectDefaults.AuthenticationScheme;}).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)// 对使用的OpenIdConnect进行设置此设置与Identityserver的config.cs中相应client配置一致才可能登录授权成功.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options {options.SignInScheme CookieAuthenticationDefaults.AuthenticationScheme;options.Authority config;options.RequireHttpsMetadata false;//必须https协议options.ClientId chrisdddmvc;//idp项目中配置的clientoptions.ClientSecret secret;options.SaveTokens true;options.ResponseType code;//响应类型// 下边是所有的scope,必须要和idp项目中一致,至少是一部分options.Scope.Clear();options.Scope.Add(roles);//rolesoptions.Scope.Add(rolename);//rolesoptions.Scope.Add(OidcConstants.StandardScopes.OpenId);//openidoptions.Scope.Add(OidcConstants.StandardScopes.Profile);//profileoptions.Scope.Add(OidcConstants.StandardScopes.Email);//email});}
这里有几个注意事项ClientId一定要填对Scope必须是Idp项目中配置的子集Scope一定要写对不然的话会报错比如我们随便把roles改成roles3当然全部粘贴过去就行其他的都有注释看看即可。这里配置也是很简单的运行到了这里我们就可以简单的调试了所有的地址都可以换成localhost来调试。没有错误的话我们就可以正式的跳转登录登录成功后跳转回来MVC项目下面我们就说说如何在MVC客户端项目中进行策略授权。MVC客户端做策略授权上边我们已经登录成功并也跳回了那现在就要根据情况设计授权了毕竟有些页面是test用户不能访问的只有超级管理员才能访问的首先在声明策略然后在控制器配置策略services.AddAuthorization(options {options.AddPolicy(CanWriteStudentData, policy policy.Requirements.Add(new ClaimRequirement(Students, Write)));options.AddPolicy(CanRemoveStudentData, policy policy.Requirements.Add(new ClaimRequirement(Students, Remove)));options.AddPolicy(CanWriteOrRemoveStudentData, policy policy.Requirements.Add(new ClaimRequirement(Students, WriteOrRemove)));});// 这里的策略内容可以任意扩展[HttpGet][Authorize(Policy CanWriteStudentData)]public IActionResult Edit(Guid? id){}
接着我们就来定义授权策略处理器 public class ClaimsRequirementHandler : AuthorizationHandlerClaimRequirement{protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ClaimRequirement requirement){var roleId context.User.Claims.FirstOrDefault(c c.Type role);var rolename context.User.Claims.FirstOrDefault(c c.Type rolename);var loginUserName context.User.Claims.FirstOrDefault(c c.Type preferred_username);if (roleId ! null roleId.Value 4 rolename ! null rolename.Value SuperAdmin){context.Succeed(requirement);}return Task.CompletedTask;}}
复杂策略授权如何写逻辑如何调上下文中的claims声明如何获取这里就不多说了默认已经会了我的第一个项目的Blog.Core的相关内容这里我们只是来看看是不是能获取到相应的Claims就行可以看到我们已经获取到了这个scope这样我们就可以任意的扩展了。登录与登出设计这个其实就很简单了我们在客户端里直接登出就行我写的比较low当然你可以自己找找例子我就简单的写了写 [Authorize]public IActionResult Login(){return Redirect(index);}public async TaskIActionResult Logout(){await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme);return View(Index);}
登录取了个巧不写内容直接加了个Authorize这样肯定就跳转到登录页了。然后设计下UI展示 _LoginPartial.cshtml 注入服务就行inject Christ3D.Domain.Interfaces.IUser SignInManagerif (SignInManager.IsAuthenticated())
{form asp-area asp-controllerHome asp-actionLogout methodpost idlogoutForm classnavbar-rightul classnav navbar-nav navbar-rightlia asp-area asp-controllerManage asp-actionIndex titleManageHello SignInManager.Name!/a/lilibutton typesubmit classbtn btn-link navbar-btn navbar-linkLog out/button/li/ul/form
}
else
{ul classnav navbar-nav navbar-rightlia asp-area asp-controllerHome asp-actionLoginLog in/a/li/ul
}
最终的展示效果是酱紫的登出登录到了这里我们就已经完成了整体流程了下边就是部署了。生产环境部署联调现在还是两个后端项目一个是IdentityServer4的部署很简单的我目前用的是Nginx部署的Https安全协议。客户端是MVC项目但是用的IIS部署的因为如何也用Nginx部署的话客户端向授权中心认证的时候一直报错错误是回调地址不匹配因为nginx部署显示的地址还是本地的但是我在idp项目里明明配置的是ddd域名错误信息是这样的但是在IIS中配置是一切正常的真的是我学术不精啊有小伙伴知道的欢迎给我留言私信拍砖这里我来个赏金20大洋给开源事业做贡献了。这个时候PC端已经一切正常了正当高兴的时候手机访问又不行了这次我很机智有了上次的JS客户端经验我直接加了一个Cookie手机移动端适配在DDD项目中新建一个扩展 public static class SameSiteHandlingExtensions{public static IServiceCollection AddSameSiteCookiePolicy(this IServiceCollection services){services.ConfigureCookiePolicyOptions(options {options.MinimumSameSitePolicy (SameSiteMode)(-1);options.OnAppendCookie cookieContext CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);options.OnDeleteCookie cookieContext CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);});return services;}private static void CheckSameSite(HttpContext httpContext, CookieOptions options){if (options.SameSite SameSiteMode.None){var userAgent httpContext.Request.Headers[User-Agent].ToString();if (DisallowsSameSiteNone(userAgent)){// For .NET Core 3.1 set SameSite (SameSiteMode)(-1)options.SameSite (SameSiteMode)(-1);}}}private static bool DisallowsSameSiteNone(string userAgent){// Cover all iOS based browsers here. This includes:// - Safari on iOS 12 for iPhone, iPod Touch, iPad// - WkWebview on iOS 12 for iPhone, iPod Touch, iPad// - Chrome on iOS 12 for iPhone, iPod Touch, iPad// All of which are broken by SameSiteNone, because they use the iOS networking stackif (userAgent.Contains(CPU iPhone OS 12) || userAgent.Contains(iPad; CPU OS 12)){return true;}// Cover Mac OS X based browsers that use the Mac OS networking stack. This includes:// - Safari on Mac OS X.// This does not include:// - Chrome on Mac OS X// Because they do not use the Mac OS networking stack.if (userAgent.Contains(Macintosh; Intel Mac OS X 10_14) userAgent.Contains(Version/) userAgent.Contains(Safari)){return true;}// Cover Chrome 50-69, because some versions are broken by SameSiteNone, // and none in this range require it.// Note: this covers some pre-Chromium Edge versions, // but pre-Chromium Edge does not require SameSiteNone.if (userAgent.Contains(Chrome/5) || userAgent.Contains(Chrome/6)){return true;}return false;}}
然后服务配置常见的错误刚刚上边我们已经遇到了两个错误其实总的来说都是配置的问题我会在博客园单写一篇文章来总结IdentityServer4的所有错误目前还没有过一段时间查看就行现在开发的还比较少。注意这两个错误然后会调试就行调试主要在F12去查看network看看请求的数据是否异常即可。到了这里基本就结束了还是建议大家多看看官网和官方Demo真的很有用。