内容简介:通过前两篇我们实现了如何在Service层如何访问数据,以及如何运用简单的加密算法对数据加密。这一篇我们将探索如何实现asp.net core的身份验证。asp.net core的身份验证有 JwtBearer和Cookie两种常见的模式,在这一篇我们将启用Cookie作为身份信息的保存。那么,我们如何启用呢?在Startup.cs 的ConfigureServices(IServiceCollection services) 方法里添加如下:
0. 前言
通过前两篇我们实现了如何在Service层如何访问数据,以及如何运用简单的加密算法对数据加密。这一篇我们将探索如何实现asp.net core的身份验证。
1. 身份验证
asp.net core的身份验证有 JwtBearer和Cookie两种常见的模式,在这一篇我们将启用Cookie作为身份信息的保存。那么,我们如何启用呢?
在Startup.cs 的ConfigureServices(IServiceCollection services) 方法里添加如下:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => { Configuration.Bind("CookieSettings",options); });
此时可以启动一个权限验证,当用户访问需要验证的页面或接口时,如果没有登录,则会自动跳转到:
https://localhost:5001/Account/Login?ReturnUrl=XXXX
其中ReturnUrl指向来源页。
1.1 设置验证
当我们在Startup类里设置启用了身份验证后,并不是访问所有接口都会被跳转到登录页面。那么如何设置访问的路径需要身份验证呢?asp.net core为我们提供了一个特性类:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] public class AuthorizeAttribute : Attribute, IAuthorizeData { public string Policy { get; set; } public string Roles { get; set; } public string AuthenticationSchemes { get; set; } }
可以看的出,这个特性类允许设置在类、方法上,可以设置多个,允许子类继承父类的特性。所以可以在控制器上设置 [Authorize]
,当在控制器上设置以后访问控制器里所有的Action都会要求验证身份;也可以单独设置在Action上,表示该Action需要验证身份,控制器里的其他方法不需要验证。
1.2 设置忽略
我们在开发过程中,会遇到这样的一组链接或者页面:请求地址同属于一个控制器下,但其中某个地址可以不用用户登录就可以访问。通常我们为了减少重复代码以及复用性等方面的考虑,会直接在控制器上设置身份验证要求,而不是在控制器里所有的Action上添加验证要求。
那么,我们如何放开其中的某个请求,可以允许它不用身份验证。
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] public class AllowAnonymousAttribute : Attribute, IAllowAnonymous { }
仔细观察,可以看得出这个特性可以设置在类、方法上,不允许多次设置,允许子类继承父类的特性。
这个特性的使用没啥可说的,不过需要注意的是,不要与AuthorizeAttribute一起使用。虽然编译上没啥问题,但实际上会对 程序员 的逻辑照成一定程度的误导。
2.保存身份
有身份验证,就必然需要保存身份。当我们从数据库中或者其他的三方服务中获取到用户信息后,我们需要将用户信息保存起来,而不是每次都向用户或者服务提供方索求信息。
在asp.net core中,Controller类里有一个属性:
public HttpContext HttpContext { get; }
HttpContext 提供了一个扩展方法,可以用来保存用户信息:
public static Task SignInAsync(this HttpContext context, ClaimsPrincipal principal);
暂时忽略这个方法的返回类型,它接受了一个ClaimsPrincipal类型的参数。我们来看下这个类的基本情况吧:
public class ClaimsPrincipal : IPrincipal { public ClaimsPrincipal(); public ClaimsPrincipal(IEnumerable<ClaimsIdentity> identities); public ClaimsPrincipal(BinaryReader reader); public ClaimsPrincipal(IIdentity identity); public ClaimsPrincipal(IPrincipal principal); public static ClaimsPrincipal Current { get; } public static Func<ClaimsPrincipal> ClaimsPrincipalSelector { get; set; } public static Func<IEnumerable<ClaimsIdentity>, ClaimsIdentity> PrimaryIdentitySelector { get; set; } public virtual IIdentity Identity { get; } public virtual IEnumerable<ClaimsIdentity> Identities { get; } public virtual IEnumerable<Claim> Claims { get; } public virtual void AddIdentities(IEnumerable<ClaimsIdentity> identities); public virtual void AddIdentity(ClaimsIdentity identity); public virtual ClaimsPrincipal Clone(); public virtual IEnumerable<Claim> FindAll(Predicate<Claim> match); public virtual IEnumerable<Claim> FindAll(string type); public virtual Claim FindFirst(string type); public virtual Claim FindFirst(Predicate<Claim> match); public virtual bool HasClaim(Predicate<Claim> match); public virtual bool HasClaim(string type, string value); public virtual bool IsInRole(string role); public virtual void WriteTo(BinaryWriter writer); }
方法和属性有点多,那么我们重点关注一下构造函数以及可以AddXXX开头的方法。
这里有一个窍门,对于一个陌生的类来说,构造函数对于类本身是个很重要的特征,我们可以通过构造函数分析出这个类需要哪些基础数据。
所以,通过简单的分析,我们需要继续了解这两个类:
public class ClaimsIdentity : IIdentity { public ClaimsIdentity(); public ClaimsIdentity(string authenticationType); public ClaimsIdentity(IIdentity identity); public ClaimsIdentity(IEnumerable<Claim> claims); public ClaimsIdentity(IEnumerable<Claim> claims, string authenticationType); public ClaimsIdentity(IIdentity identity, IEnumerable<Claim> claims); public ClaimsIdentity(string authenticationType, string nameType, string roleType); public ClaimsIdentity(IEnumerable<Claim> claims, string authenticationType, string nameType, string roleType); public ClaimsIdentity(IIdentity identity, IEnumerable<Claim> claims, string authenticationType, string nameType, string roleType); } public class Claim { public Claim(BinaryReader reader); public Claim(BinaryReader reader, ClaimsIdentity subject); public Claim(string type, string value); public Claim(string type, string value, string valueType); public Claim(string type, string value, string valueType, string issuer); public Claim(string type, string value, string valueType, string issuer, string originalIssuer); public Claim(string type, string value, string valueType, string issuer, string originalIssuer, ClaimsIdentity subject); protected Claim(Claim other); protected Claim(Claim other, ClaimsIdentity subject); public string Type { get; } public ClaimsIdentity Subject { get; } public IDictionary<string, string> Properties { get; } public string OriginalIssuer { get; } public string Issuer { get; } public string ValueType { get; } public string Value { get; } protected virtual byte[] CustomSerializationData { get; } public virtual Claim Clone(); public virtual Claim Clone(ClaimsIdentity identity); public override string ToString(); public virtual void WriteTo(BinaryWriter writer); protected virtual void WriteTo(BinaryWriter writer, byte[] userData); }
所以,看到这里就会发现,我们可以通过以下方式保存信息:
List<Claim> claims = null; var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); HttpContext.SignInAsync( CookieAuthenticationDefaults.AuthenticationScheme,new ClaimsPrincipal(identity));
这时候,数据就可以保存在Cookie里了,那么如何在控制器中获取到数据呢:
public ClaimsPrincipal User { get; }
在控制器中,提供了这样一个属性,当然如果想要正确获取到值的话,需要在 Startup.cs类中的添加如下配置:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // ……省略其他配置 app.UseAuthorization(); app.UseAuthentication(); // ……省略其他配置 }
3. 总结
在这一篇中,简单介绍了asp.net core的identity,下一篇将从实际上带领大家设置不一样的identity以及Authorize验证。
更多内容烦请关注 我的博客《高先生小屋》
以上所述就是小编给大家介绍的《【asp.net core 系列】13 Identity 身份验证入门》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 表单正则验证及文件上传验证功能
- angular 实现同步验证器跨字段验证
- Spring Security验证流程剖析及自定义验证方法
- TensorFlow 推出数据验证函数库 TFDV,用于分析和验证
- TensorFlow 推出数据验证函数库 TFDV,用于分析和验证
- 滑动验证码的原理并利用 Vue 实现滑动验证码
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Programming Python
Mark Lutz / O'Reilly Media / 2006-8-30 / USD 59.99
Already the industry standard for Python users, "Programming Python" from O'Reilly just got even better. This third edition has been updated to reflect current best practices and the abundance of chan......一起来看看 《Programming Python》 这本书的介绍吧!