AspNetAuthorizationWorkshop

2025-12-07 0 562

ASP.NET核心授权实验室

这是为ASP.NET核心授权实验室的过程,现在已更新为ASP.NET Core 2.1和VS2017。 (如果您仍在使用1.x,则实验室的较旧版本可在Core1x分支中使用。)

该实验室使用模型视图控制器模板,因为这是每个人到现在一直在使用的,这是绝大多数人的最熟悉的起点。

官方授权文档在https://docs.a*s**p.net/en/latest/security/authorization/authorization/index.html。

提示:在每个阶段停止完成应用程序时,请始终关闭浏览器以清除身份cookie。

步骤0:准备

创建一个新的空白,ASP.NET项目。

  • 文件>新项目> Visual C#> .NET Core
  • 选择ASP.NET Core Web应用程序,为项目提供AuthorizationLab的名称,然后单击“确定”。
  • 选择空模板,请确保在项目类型上方的下拉列表中选择ASP.NET Core 2.1,然后单击“确定”。

将MVC添加到应用程序中。

  • 编辑Startup.cs并添加services.AddMvc();ConfigureServices()方法的顶部;
  • 编辑Configure()方法,删除现有代码。
  • 在现在的空Configure();将以下代码添加到设置MVC默认路由;
 app . UseMvc ( routes =>
{
     routes . MapRoute (
          name : \"default\" ,
          template : \"{controller=Home}/{action=Index}/{id?}\" ) ;
} ) ;
  • 创建一个Controllers文件夹
  • 使用VS Controller模板在控制器目录中创建HomeController.cs文件,或从头开始创建它并确保从Controller继承并具有Index()方法,该方法返回一个视图,例如
 using Microsoft . AspNetCore . Mvc ;

namespace AuthorizationLab . Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index ( )
        {
            return View ( ) ;
        }
    }
}
  • 创建一个Views文件夹。
  • Views下创建一个Home文件夹。
  • Views\\Home文件夹中创建一个Index.cshtml文件,然后对其进行编辑以包含Hello World。
  • 运行您的应用程序并确保您看到Hello World。

步骤1:设置身份验证

  • 在ASP.NET Core 2.1中, Microsoft.AspNetCore.App Meta软件包包含所有身份验证和授权软件包,因此您无需添加任何额外的软件包或参考。
  • Open startup.cs
  • 添加app.UseAuthentication();Configure()方法的顶部。
  • 通过将以下内容添加到ConfigureServices()方法的顶部,将Cookie Mifferware添加到身份验证服务中。
 services . AddAuthentication ( CookieAuthenticationDefaults . AuthenticationScheme )
    . AddCookie ( CookieAuthenticationDefaults . AuthenticationScheme ,
        options => 
        {
                options . LoginPath = new PathString ( \"/Account/Login/\" ) ;
                options . AccessDeniedPath = new PathString ( \"/Account/Forbidden/\" ) ;
        } ) ;
  • 编辑主控制器,然后将[Authorize]属性添加到控制器。
  • 运行项目和恐慌。您会遇到404错误。您没有登录页面。
  • 现在,在Controllers文件夹中创建Account控制器, AccountController.cs 。创建一个Login()操作和Forbidden()操作。
 using Microsoft . AspNetCore . Mvc ;

namespace AuthorizationLab . Controllers
{
    public class AccountController : Controller
    {
        public IActionResult Login ( )
        {
            return View ( ) ;
        }

        public IActionResult Forbidden ( )
        {
            return View ( ) ;
        }
    }
}
  • Views文件夹下创建一个Account文件夹,并为操作创建相应的视图, Login.cshtmlForbidden.cshtml
  • 在每个视图中添加一些文本,以便您可以判断要显示哪个视图,然后运行您的项目。您会看到您最终进入登录视图。
  • 返回Account控制器。更改Login操作以创建Principal ,并使用以下代码坚持下去。这将创建用户信息并将其放入cookie中。这就假装基于表单的登录系统通常会发生的事情。
 public async Task < IActionResult > Login ( string returnUrl = null )
{
    const string Issuer = \"https://*cont*os*o.com\" ;
    var claims = new List < Claim > ( ) ;
    claims . Add ( new Claim ( ClaimTypes . Name , \"barry\" , ClaimValueTypes . String , Issuer ) ) ;
    var userIdentity = new ClaimsIdentity ( \"SuperSecureLogin\" ) ;
    userIdentity . AddClaims ( claims ) ;
    var userPrincipal = new ClaimsPrincipal ( userIdentity ) ;

    await HttpContext . SignInAsync (
        CookieAuthenticationDefaults . AuthenticationScheme ,
        userPrincipal ,
        new AuthenticationProperties
        {
            ExpiresUtc = DateTime . UtcNow . AddMinutes ( 20 ) ,
            IsPersistent = false ,
            AllowRefresh = false
        } ) ;

    return RedirectToLocal ( returnUrl ) ;
}

private IActionResult RedirectToLocal ( string returnUrl )
{
    if ( Url . IsLocalUrl ( returnUrl ) )
    {
        return Redirect ( returnUrl ) ;
    }
    else
    {
        return RedirectToAction ( \"Index\" , \"Home\" ) ;
    }
}
  • 最后,编辑Home\\Index视图以显示身份的名称声明。用以下代码替换该视图的内容。此代码故意有些复杂,因为用户主体可以包含多个身份验证的身份。这很少发生,坦率地说,您是否已经写了代码来执行此操作,但是您应该知道此边缘情况。
 @using System.Security.Claims;

@if (!User.Identities.Any(u => u.IsAuthenticated))
{
    <h1>Hello World</h1>
}
else
{
    <h1>Hello @User.Identities.First(
      u => u.IsAuthenticated && 
      u.HasClaim(c => c.Type == ClaimTypes.Name)).FindFirst(ClaimTypes.Name).Value</h1>
}
  • 运行项目,看看会发生什么。您应该看到“你好巴里”。代码claims.Add(new Claim(ClaimTypes.Name, \"barry\", ClaimValueTypes.String, Issuer));帐户控制器中的Login()方法内部是设置姓名声明的内容,并且是视图所显示的。

请记住要关闭浏览器以清除身份cookie,然后再进入下一步。

步骤2:授权所有事情

  • 首先从Home控制器中删除Authorize属性。
  • Startup.cs中的ConfigureServices()中更改AddMvc()调用,以将默认授权策略添加到MVC配置中。
 services . AddMvc ( config =>
{
    var policy = new AuthorizationPolicyBuilder ( )
                     . RequireAuthenticatedUser ( )
                     . Build ( ) ;
    config . Filters . Add ( new AuthorizeFilter ( policy ) ) ;
} ) ;
  • 跑步并观察一切爆炸成无限的重定向循环。为什么?您已经使每个页面都需要身份验证。这甚至包括登录页面。
  • 现在,将[AllowAnonymous]属性添加到Account控制器中,再次运行并查看用户已登录。 AllowAnonymous允许您将控制器或操作方法标记为不需要身份验证,即使您需要在其他地方进行身份验证。

请记住要关闭浏览器以清除身份cookie,然后再进入下一步。

步骤3:角色

  • 转到Home控制器,并为控制器或索引操作方法添加具有角色需求的Authorize属性;
 [ Authorize ( Roles = \"Administrator\" ) ]
  • 运行应用程序并确认您已重定向到Forbidden视图。发生这种情况是因为您具有身份,但这不是管理员角色的一部分。
  • 关闭浏览器以清除身份曲奇。
  • 返回到AccountController并添加第二个claims.Add()行,如下所示。这将管理员价值的角色主张添加到已发行的身份。
 claims . Add ( new Claim ( ClaimTypes . Role , \"Administrator\" , ClaimValueTypes . String , Issuer ) ) ;
  • 运行应用程序并确认您已登录。

请记住要关闭浏览器以清除身份cookie,然后再进入下一步。

步骤4:简单政策

  • 返回到Startup.cs ,然后在ConfigureServices() services.AddAuthentication() )调用。
  • After services.AddAuthentication()将调用添加到services.AddAuthorization()并创建一个简单的策略,如下所示。
 services . AddAuthorization ( options =>
{
    options . AddPolicy ( \"AdministratorOnly\" , policy => policy . RequireRole ( \"Administrator\" ) ) ;
} ) ;
  • 此策略等同于您在步骤3中Authorize属性参数中使用的角色检查。
  • 现在,更改家庭控制器Authorize属性需要策略,而不是使用角色参数。
 [ Authorize ( Policy = \"AdministratorOnly\" ) ]
  • 运行该应用程序并确认您仍然可以看到主页。所改变的只是您指定要求的方式。您没有将角色名称嵌入到属性中,而是写了一个指定角色名称的策略。
  • 关闭浏览器以清除您的身份cookie。
  • 现在添加第二个政策,这次需要索赔。
 services . AddAuthorization ( options =>
{
    options . AddPolicy ( \"AdministratorOnly\" , policy => policy . RequireRole ( \"Administrator\" ) ) ;
    options . AddPolicy ( \"EmployeeId\" , policy => policy . RequireClaim ( \"EmployeeId\" ) ) ;
} ) ;
  • Account控制器中Login操作发出的身份添加合适的索赔。
 claims . Add ( new Claim ( \"EmployeeId\" , string . Empty , ClaimValueTypes . String , Issuer ) ) ;
  • 使用新的策略名称将新的Authorize属性添加到家庭控制器。
 [ Authorize ( Policy = \"EmployeeId\" ) ]
  • 运行该应用程序并确保您可以查看主页。
  • 不过,这是一项相当无用的检查。索赔由索赔名称和索赔价值组成。您确实想检查值,而不仅仅是索赔的存在。幸运的是,有一个参数。更改EmployeeId政策以需要许多值之一;
 options . AddPolicy ( \"EmployeeId\" , policy => policy . RequireClaim ( \"EmployeeId\" , \"123\" , \"456\" ) ) ;
  • 再次运行该应用程序,空索赔将被拒绝,您最终将在禁止页面上。
  • 关闭您的浏览器以清除身份cookie。
  • 更改身份发行代码以对Login操作具有适当的索赔价值,如下所示,然后重试。
 claims . Add ( new Claim ( \"EmployeeId\" , \"123\" , ClaimValueTypes . String , Issuer ) ) ;

如果保单有多个索赔要求,则必须满足所有索赔要求才能获得成功。

请记住要关闭浏览器以清除身份cookie,然后再进入下一步。

步骤5:基于代码的政策

基于代码的策略由要求组成,实施IAuthorizationRequirement和用于要求的处理程序,实施AuthorizationHandler<T> t是要求。

  • Account控制器中的Login操作中,向用户本金添加出生日期。
 claims . Add ( new Claim ( ClaimTypes . DateOfBirth , \"1970-06-08\" , ClaimValueTypes . Date ) ) ;
  • 现在创建自定义要求和处理程序类;称为MuniminAgeRequrement。为了简单起见,我们将在这里使用单个类以及处理程序。
 using System ;
using System . Security . Claims ;
using System . Threading . Tasks ;
using Microsoft . AspNetCore . Authorization ;

namespace AuthorizationLab
{
    public class MinimumAgeRequirement : AuthorizationHandler < MinimumAgeRequirement > , IAuthorizationRequirement
    {
        int _minimumAge ;

        public MinimumAgeRequirement ( int minimumAge )
        {
            _minimumAge = minimumAge ;
        }

        protected override Task HandleRequirementAsync (
            AuthorizationHandlerContext context , 
            MinimumAgeRequirement requirement )
        {
            if ( ! context . User . HasClaim ( c => c . Type == ClaimTypes . DateOfBirth ) )
            {
                return Task . CompletedTask ;
            }

            var dateOfBirth = Convert . ToDateTime (
                context . User . FindFirst ( c => c . Type == ClaimTypes . DateOfBirth ) . Value ) ;

            int calculatedAge = DateTime . Today . Year - dateOfBirth . Year ;
            if ( dateOfBirth > DateTime . Today . AddYears ( - calculatedAge ) )
            {
                calculatedAge -- ;
            }

            if ( calculatedAge >= _minimumAge )
            {
                context . Succeed ( requirement ) ;
            }

            return Task . CompletedTask ;
        }
    }
}
  • 在addauthorization函数中创建Over21策略;
 options . AddPolicy ( \"Over21Only\" , policy => policy . Requirements . Add ( new MinimumAgeRequirement ( 21 ) ) ) ;
  • 使用Authorize属性将其应用于Home控制器。
  • 运行该应用程序并确保您可以查看主页。
  • 实验出生价值日期(例如,成为去年的一年)以使授权失败。在继续前进之前,不要忘记将其设置回传递值。

请记住要关闭浏览器以清除身份cookie,然后再进入下一步。

步骤6:多个处理程序需要

您可能已经注意到处理程序的返回,什么都没有(严格来说Task.CompletedTask; 。处理人员通过调用context.Succeed(requirement); 。您可能会问自己是否有context.Succeed()context.Fail() ?有,但是如果不满足您的要求,您根本不应该触摸上下文。现在您可能会问为什么不呢?出色地 …

有时,您可能需要多个处理程序来获得授权要求,例如,有多种方法可以满足要求。微软的办公室门带有您的Microsoft徽章,但是在您忘记徽章的日子里,您可以去接待处并获得临时通行证,接待员将让您穿过大门。因此,有两种方法可以满足单一条目要求。在ASP.NET核心授权模型中,这将作为单个要求的两个处理程序实现。

  • 首先,写一个新的IAuthorizationRequirementOfficeEntryRequirement
 using Microsoft . AspNetCore . Authorization ;

namespace AuthorizationLab
{
    public class OfficeEntryRequirement : IAuthorizationRequirement
    {
    }
}
  • 现在编写一个AuthorizationHandler ,检查当前身份是否具有由雇主HasBadgeHandler发出的徽章号索赔。
 using Microsoft . AspNetCore . Authorization ;

namespace AuthorizationLab
{
    public class HasBadgeHandler : AuthorizationHandler < OfficeEntryRequirement >
    {
        protected override Task HandleRequirementAsync (
          AuthorizationHandlerContext context , 
          OfficeEntryRequirement requirement )
        {
            if ( ! context . User . HasClaim ( c => c . Type == \"BadgeNumber\" && 
                                            c . Issuer == \"https://*cont*os*o.com\" ) )
            {
                return Task . CompletedTask ;
            }

            context . Succeed ( requirement ) ;

            return Task . CompletedTask ;
        }
    }
}

这会照顾记得合适公司发行的徽章的人(在所有多家公司都有入场卡之后,您想检查该卡是否由您期望的公司发行。 Claims类具有发行人的财产,详细介绍了发出索赔的人,因此在我们的情况下,这是发行徽章的人)。

但是,那些忘记并拥有临时徽章的人呢?您可以将其全部放入一个处理程序中,但是处理程序和要求是可以重复使用的。您可以将上面显示的HasBadgeHandler用于其他事项,而不仅仅是办公室条目(例如,Microsoft代码签名基础架构需要我们的Office Badge的智能卡来触发作业)。

  • 为了应付临时徽章,撰写另一个AuthorizationHandlerHasTemporaryPassHandler
 using System ;
using Microsoft . AspNetCore . Authorization ;

namespace AuthorizationLab
{
    public class HasTemporaryPassHandler : AuthorizationHandler < OfficeEntryRequirement >
    {
        protected override Task HandleRequirementAsync (
          AuthorizationHandlerContext context , 
          OfficeEntryRequirement requirement )
        {
            if ( ! context . User . HasClaim ( c => c . Type == \"TemporaryBadgeExpiry\" &&
                                            c . Issuer == \"https://*cont*os*o.com\" ) )
            {
                return Task . CompletedTask ;
            }

            var temporaryBadgeExpiry = 
                Convert . ToDateTime ( context . User . FindFirst (
                                       c => c . Type == \"TemporaryBadgeExpiry\" &&
                                       c . Issuer == \"https://*cont*os*o.com\" ) . Value ) ;

            if ( temporaryBadgeExpiry > DateTime . Now )
            {
                context . Succeed ( requirement ) ;
            }

            return Task . CompletedTask ;
        }
    }
}

请注意,没有处理程序调用Context.Fail()。 context.fail()有时会有授权无法继续,例如,即使还有另一个处理程序,“我的整个用户数据库都在纵火。”或“我正在寻找的用户刚刚被阻止,但其他后端系统可能尚未更新。”

  • 接下来,为要求创建一个策略,在授权配置内的Startup.cs中的ConfigureServices()中注册它。
 options . AddPolicy ( \"BuildingEntry\" , policy => policy . Requirements . Add ( new OfficeEntryRequirement ( ) ) ) ;
  • 返回到Account控制器的Login方法,并添加合适的徽章ID声明。
 claims . Add ( new Claim ( \"BadgeNumber\" , \"123456\" , ClaimValueTypes . String , Issuer ) ) ;
  • 最后,将创建的策略应用于使用Authorize属性中的Home控制器中的Index视图。
 [ Authorize ( Policy = \"BuildingEntry\" ) ]
  • 运行该应用程序,哦,亲爱的,我们被禁止禁止。为什么?

处理程序保存在ASP.NET DI容器中。在以前的样本中,我们将要求和处理程序组合在一个类中,因此授权系统知道它,而无需在DI中手动注册。现在,我们有单独的处理程序需要在DI容器中注册它们,然后才能找到它们。

  • 打开Startup.cs和Inside ConfigureServices()通过将以下内容添加到ConfigureServices()方法的底部,在DI容器中注册处理程序。请注意,它们不必是单例,您可以使用DI系统将构造函数参数注入处理程序,因此,例如,如果您要注入EF存储库,则可能需要将处理程序添加为scopepter scopep of Request。
 services . AddSingleton < IAuthorizationHandler , HasBadgeHandler > ( ) ;
services . AddSingleton < IAuthorizationHandler , HasTemporaryPassHandler > ( ) ;
  • 再次运行该应用程序,您可以看到授权工作。
  • 尝试评论BadGenumber主张并用临时性的呼吸道主张代替,并记住每次关闭浏览器以清除身份cookie,以便将其重新创建您的新主张。
 claims . Add ( new Claim ( \"TemporaryBadgeExpiry\" , 
                     DateTime . Now . AddDays ( 1 ) . ToString ( ) , 
                     ClaimValueTypes . String , 
                     Issuer ) ) ;
  • 运行该应用程序,并且您仍然获得授权,因为现在临时徽章的处理程序满足了建筑物的要求。
  • 更改临时徽章索赔,以使其过期;在运行新代码之前,请记住关闭浏览器以清除身份cookie。
 claims . Add ( new Claim ( \"TemporaryBadgeExpiry\" , 
                     DateTime . Now . AddDays ( - 1 ) . ToString ( ) , 
                     ClaimValueTypes . String , 
                     Issuer ) ) ;
  • 重新运行该应用程序,您会看到您被禁止。
  • 删除BadGenumber索赔代码的临时徽章索赔,因此您要重新获得授权,关闭浏览器以清除身份cookie并重新运行该应用程序,以确保您不再被禁止。

步骤7:基于资源的要求

到目前为止,我们涵盖了仅基于用户身份的要求。但是,经常授权需要访问资源。例如,文档类可能有作者,只有作者才能编辑文档,而其他作者可以查看它。

  • 创建一个资源类,具有int ID属性的Documentstring作者属性。
 namespace AuthorizationLab
{
    public class Document
    {
        public int Id { get ; set ; }
        public string Author { get ; set ; }
    }
}
  • 为文档类创建一个存储库接口, IDocumentRepository
 using System . Collections . Generic ;

下载源码

通过命令行克隆项目:

git clone https://github.com/blowdart/AspNetAuthorizationWorkshop.git

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

申明:本文由第三方发布,内容仅代表作者观点,与本网站无关。对本文以及其中全部或者部分内容的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。本网发布或转载文章出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,也不代表本网对其真实性负责。

左子网 开发教程 AspNetAuthorizationWorkshop https://www.zuozi.net/32041.html

php image resize
上一篇: php image resize
ui router
下一篇: ui router
常见问题
  • 1、自动:拍下后,点击(下载)链接即可下载;2、手动:拍下后,联系卖家发放即可或者联系官方找开发者发货。
查看详情
  • 1、源码默认交易周期:手动发货商品为1-3天,并且用户付款金额将会进入平台担保直到交易完成或者3-7天即可发放,如遇纠纷无限期延长收款金额直至纠纷解决或者退款!;
查看详情
  • 1、描述:源码描述(含标题)与实际源码不一致的(例:货不对板); 2、演示:有演示站时,与实际源码小于95%一致的(但描述中有”不保证完全一样、有变化的可能性”类似显著声明的除外); 3、发货:不发货可无理由退款; 4、安装:免费提供安装服务的源码但卖家不履行的; 5、收费:价格虚标,额外收取其他费用的(但描述中有显著声明或双方交易前有商定的除外); 6、其他:如质量方面的硬性常规问题BUG等。 注:经核实符合上述任一,均支持退款,但卖家予以积极解决问题则除外。
查看详情
  • 1、左子会对双方交易的过程及交易商品的快照进行永久存档,以确保交易的真实、有效、安全! 2、左子无法对如“永久包更新”、“永久技术支持”等类似交易之后的商家承诺做担保,请买家自行鉴别; 3、在源码同时有网站演示与图片演示,且站演与图演不一致时,默认按图演作为纠纷评判依据(特别声明或有商定除外); 4、在没有”无任何正当退款依据”的前提下,商品写有”一旦售出,概不支持退款”等类似的声明,视为无效声明; 5、在未拍下前,双方在QQ上所商定的交易内容,亦可成为纠纷评判依据(商定与描述冲突时,商定为准); 6、因聊天记录可作为纠纷评判依据,故双方联系时,只与对方在左子上所留的QQ、手机号沟通,以防对方不承认自我承诺。 7、虽然交易产生纠纷的几率很小,但一定要保留如聊天记录、手机短信等这样的重要信息,以防产生纠纷时便于左子介入快速处理。
查看详情

相关文章

猜你喜欢
发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务