mvc 项目 webconfig 打开错误_【实战 Ids4】 又一个项目迁移完成(MVC)
发布日期:2021-06-25 19:30:29 浏览次数:8 分类:技术文章

本文共 9848 字,大约阅读时间需要 32 分钟。

63159a797294bc48a94d5ffccb527aa2.png
63159a797294bc48a94d5ffccb527aa2.png迎周一,腊月十九,小年倒计时

新年还有两周时间就要到了,学习可不能停,这几天一直在加班调休,周末也如此,不过也是趁着半夜凌晨的时间,继续迁移我的项目到IdentityServer4统一认证授权中心Blog.IdentityServer上,也是基本统一了,目前进度如下:

01、前后端分离全家桶已经完成升级:Blog.Core为api,Blog.Admin为后台管理,Blog.Vue为前台信息展示已经全部搞定,具体的代码查看指定Github的分支即可,分支名基本都是Is4,Ids4等字样;

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 clientnew Client{
ClientId = "chrisdddmvc", ClientName="Chris DDD MVC项目", ClientSecrets = { new Secret("secret".Sha256()) }, AllowedGrantTypes = GrantTypes.Code, RequireConsent = false, RequirePkce = true, AlwaysIncludeUserClaimsInIdToken=true,//将用户所有的claims包含在IdToken内 // 登录回调 RedirectUris = { "http://ddd.neters.club/signin-oidc" }, // 登出回调地址 PostLogoutRedirectUris = { "http://ddd.neters.club/signout-callback-oidc" },    // 注意这些scope,一定是上边已经定义好的资源 AllowedScopes = new List
{
IdentityServerConstants.StandardScopes.OpenId, IdentityServerConstants.StandardScopes.Profile, IdentityServerConstants.StandardScopes.Email, "roles",        "rolename", }}

这里就强调两点,就是配置一下回调地址,然后就是AlwaysIncludeUserClaimsInIdToken要设置为true,以方便我们后边要从claims声明中获取返回的值。

当然,最后还有一个知识点,就是scope中,如果想要自定义的话,需要先在claims中注册添加,然后在GetIdentityResources中配置:

// scopes define the resources in your system public static IEnumerableGetIdentityResources() {
return new List {
new IdentityResources.OpenId(), new IdentityResources.Profile(), new IdentityResources.Email(), new IdentityResource("roles", "角色", new List
{ JwtClaimTypes.Role }),         new IdentityResource("rolename", "角色名", new List
 { "rolename" }), }; }

这里配置就是很简单的,咱们继续看看如何在MVC中配置。

ChristDDD如何配置

如果你之前看过或者用到了我的DDD项目,会发现其实本来是用Identity写的,这次我们迁移到Ids4后,需要做一些变化,具体的直接下载我的Ids4分支就行了,修改的内容比较多。

首先我们把响应的认证服务给抽出来,单独封装,上边的是Ids4的,下边的是普通的Identity的:

72745ab4a2dca083ea9bf50a500e3ae6.png

然后注入服务:

// 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项目中配置的client options.ClientSecret = "secret"; options.SaveTokens = true; options.ResponseType = "code";//响应类型 // 下边是所有的scope,必须要和idp项目中一致,至少是一部分 options.Scope.Clear(); options.Scope.Add("roles");//"roles" options.Scope.Add("rolename");//"roles" options.Scope.Add(OidcConstants.StandardScopes.OpenId);//"openid" options.Scope.Add(OidcConstants.StandardScopes.Profile);//"profile" options.Scope.Add(OidcConstants.StandardScopes.Email);//"email" });  }

这里有几个注意事项:ClientId一定要填对,Scope必须是Idp项目中配置的子集,Scope一定要写对,不然的话,会报错,比如我们随便把roles改成roles3:

74f556ca197da153965abe87e6d29f59.png

当然全部粘贴过去就行,其他的都有注释,看看即可。

这里配置也是很简单的,运行到了这里,我们就可以简单的调试了,所有的地址,都可以换成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 : AuthorizationHandler  {
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就行:

4cadd708737938ac2f939ebeaa47a535.png

可以看到我们已经获取到了这个scope,这样我们就可以任意的扩展了。

登录与登出设计

这个其实就很简单了,我们在客户端里,直接登出就行,我写的比较low,当然你可以自己找找例子,我就简单的写了写:

[Authorize] public IActionResult Login() {
return Redirect("index"); } public async TaskLogout() {
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme);     return View("Index"); }

登录取了个巧,不写内容,直接加了个Authorize,这样肯定就跳转到登录页了。

然后设计下UI展示 _LoginPartial.cshtml ,注入服务就行:

@inject Christ3D.Domain.Interfaces.IUser SignInManager@if (SignInManager.IsAuthenticated()){

最终的展示效果是酱紫的,登出:

2d0707c561ea9df0c8e342cbd146022b.png

登录:

23e7a032230515a5973fb95e7e271d18.png

到了这里,我们就已经完成了整体流程了!下边就是部署了。

生产环境部署联调

现在还是两个后端项目,一个是IdentityServer4的部署,很简单的,我目前用的是Nginx部署的,Https安全协议。

客户端是MVC项目,但是用的IIS部署的,因为如何也用Nginx部署的话,客户端向授权中心认证的时候,一直报错,错误是回调地址不匹配,因为nginx部署,显示的地址还是本地的:

4b6b756cd7a2a67d7069437dbe3455d3.png

但是我在idp项目里,明明配置的是ddd域名:

2788cc537e990e94b07eaa4d5a276411.png

错误信息是这样的:

a07437817dab3d0e8fbefb295a55de98.png

33a3f7410d5733eb8da3f62b69d1b83b.png

但是在IIS中配置,是一切正常的,真的是我学术不精啊,有小伙伴知道的,欢迎给我留言私信拍砖,这里我来个赏金(20大洋),给开源事业做贡献了。

这个时候,PC端已经一切正常了,正当高兴的时候,手机访问,又不行了,这次我很机智,有了上次的JS客户端经验,我直接加了一个Cookie

手机移动端适配

在DDD项目中,新建一个扩展:

public static class SameSiteHandlingExtensions {
public static IServiceCollection AddSameSiteCookiePolicy(this IServiceCollection services) {
services.Configure(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 SameSite=None, because they use the iOS networking stack if (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 SameSite=None, // and none in this range require it. // Note: this covers some pre-Chromium Edge versions, // but pre-Chromium Edge does not require SameSite=None. if (userAgent.Contains("Chrome/5") || userAgent.Contains("Chrome/6")) {
return true; } return false; } }

然后服务配置:

af6d6920f39074550865c2b6b97f78e6.png

常见的错误

刚刚上边我们已经遇到了两个错误,其实总的来说,都是配置的问题,我会在博客园单写一篇文章,来总结IdentityServer4的所有错误,目前还没有,过一段时间查看就行,现在开发的还比较少。注意这两个错误,然后会调试就行,调试主要在F12,去查看network,看看请求的数据是否异常即可。

f307c253d3f677aae6bdce4f809ef15b.png

90afc5691b9c19f653a6b035ef3c8ea0.png

到了这里,基本就结束了,还是建议大家多看看官网和官方Demo,真的很有用。

转载地址:https://blog.csdn.net/weixin_39622901/article/details/111704031 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:hive报错 spark_Spark是否能替代Hive
下一篇:挖掘机燃料_简阳水陆二用挖掘机哪里租赁

发表评论

最新留言

很好
[***.229.124.182]2024年03月30日 15时34分26秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

spring boot 与 Ant Design of Vue 实现新增组织(二十四) 2019-04-27
spring boot 与 Ant Design of Vue 实现修改组织(二十五) 2019-04-27
spring boot 与 Ant Design of Vue 实现删除组织(二十六) 2019-04-27
spring boot 与 Ant Design of Vue 实现获取用户列表(二十七) 2019-04-27
spring boot 与 Ant Design of Vue 实现删除用户(三十) 2019-04-27
spring boot 与 Ant Design of Vue 鉴权体系获取用户信息的实现(三十二) 2019-04-27
Druid连接池实现自定义场景的多数据库的连接 2019-04-27
PL/SQL数据库管理工具的使用 2019-04-27
带你玩转属于自己的spring-boot-starter系列(一) 2019-04-27
带你玩转属于自己自己的spring-boot-starter系列(二) 2019-04-27
带你玩转属于自己的spring-boot-starter系列(三) 2019-04-27
基于SnowFlake算法如何让分库分表中不同的ID落在同一个库的算法的实现 2019-04-27
基于springboot的ShardingSphere5.X的分库分表的解决方案之分表解决方案(一) 2019-04-27
基于springboot的ShardingSphere5.X的分库分表的解决方案之关联查询解决方案(三) 2019-04-27
Linux文件管理参考 2019-04-27
FTP文件管理项目(本地云)项目日报(二) 2019-04-27
FTP文件管理项目(本地云)项目日报(三) 2019-04-27
FTP文件管理项目(本地云)项目日报(七) 2019-04-27
FTP文件管理项目(本地云)项目日报(九) 2019-04-27
以练代学设计模式 -- FTP文件管理项目 2019-04-27