验证(Authentication)和授权(Authorization)(一):
发布日期:2021-08-21 13:17:38 浏览次数:28 分类:技术文章

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

 

采用ASP.NET Web API 提供的IAuthenticationFilter和IAuthorizationFilter接口分别实现验证和授权。其中用到IIdentity和IPrincipal接口。

IIdentity的具体类型用来标识通过验证的用户身份,由用户凭据(Credential)来创建一个指定名称的用户。

接口定义:

    //定义标识对象的基本功能。

    public interface IIdentity

    {

        // 获取所使用的身份验证的类型。

        string  AuthenticationType { get; }

        // 获取一个值,该值指示是否验证了用户。

        bool  IsAuthenticated { get; }

        // 获取当前用户的名称

        string  Name { get; }

    }

不同的验证类型,对IIdentity有不同的实现方式。如:WindowsIdentity(Windows集成)、FormsIdentity(Forms)和GenericIdentity(一般用户)等。

如果自定义实现验证方式,可以采用GenericIdentity来标识用户身份,已通过验证的用户是一个指定名称的GenericIdentity。

GenericIdentity类型定义:

  public class GenericIdentity : ClaimsIdentity

    {

        //     使用指定的 System.Security.Principal.GenericIdentity 对象初始化 System.Security.Principal.GenericIdentity

        //     类的新实例。

        protected GenericIdentity(GenericIdentity identity);

        //     初始化 System.Security.Principal.GenericIdentity 类的新实例,该类表示具有指定名称的用户。

        public GenericIdentity(string name);

        //     初始化 System.Security.Principal.GenericIdentity 类的新实例,该类表示具有指定名称和身份验证类型的用户。

        public GenericIdentity(string name, string type);

        //     获取用于标识用户的身份验证的类型。

        public override string AuthenticationType { get; }

        //     为用户获取此最常用标识表示的所有声明。

        public override IEnumerable<Claim> Claims { get; }

        //     获取一个值,该值指示是否验证了用户。

        public override bool IsAuthenticated { get; }

        //     获取用户的名称。

        public override string Name { get; }

        //     创建作为当前实例副本的新对象。

        public override ClaimsIdentity Clone();

    }

IPrincipal的具体类型表示一个已通过验证并获得授权的对象。

接口定义:

    public interface IPrincipal

    {

        //     获取当前用户的标识。

        IIdentity Identity { get; }

        //     确定当前用户是否属于指定的角色。

        bool IsInRole(string role);

    }

GenericPrincipal类型,用用户标识和角色名称数组来初始化。

    public class GenericPrincipal : ClaimsPrincipal

    {

        //     从用户标识和角色名称数组(标识表示的用户属于该数组)初始化 System.Security.Principal.GenericPrincipal

        //     类的新实例。

        public GenericPrincipal(IIdentity identity, string[] roles);

        //     获取当前 System.Security.Principal.GenericPrincipal 表示的用户的 System.Security.Principal.GenericIdentity。

        public override IIdentity Identity { get; }

        //     确定当前 System.Security.Principal.GenericPrincipal 是否属于指定的角色。

        public override bool IsInRole(string role);

    }

IAuthenticationFilter接口定义:

public interface IAuthenticationFilter : IFilter

{
Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken);
Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken);
}

其中AuthenticateAsync方法用于实现用户认证,而ChallengeAsync方法在认证失败的情况下,生成“质询(Challenge)”结果。

用自定义AuthenticateAttribute类型实现Basic认证:

[AttributeUsage(AttributeTargets.Class|AttributeTargets.Method)]

public class AuthenticateAttribute : FilterAttribute, IAuthenticationFilter
{
private static readonly Dictionary<string, string> UserAccount;
static AuthenticateAttribute()
{
UserAccount = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{"CHN", "china"}
};
}

public Task AuthenticateAsync(HttpAuthenticationContext context,

System.Threading.CancellationToken cancellationToken)
{
var headerValue = context.Request.Headers.Authorization;

if (null == headerValue || headerValue.Scheme != "Basic")

return Task.Factory.StartNew(() => { }, cancellationToken);

var byteArray = Convert.FromBase64String(headerValue.Parameter);

var credential = Encoding.UTF8.GetString(byteArray);
var split = credential.Split(':');

if (split.Length != 2) return Task.Factory.StartNew(() => { }, cancellationToken);

var userName = split[0];

string password;

if (!UserAccount.TryGetValue(userName, out password))

return Task.Factory.StartNew(() => { }, cancellationToken);

if (password != split[1]) return Task.Factory.StartNew(() => { }, cancellationToken);

var identity=new GenericIdentity(userName);
IPrincipal user = new GenericPrincipal(identity,new string[0]);
context.Principal = user;

return Task.FromResult<object>(null);

}

public Task ChallengeAsync(HttpAuthenticationChallengeContext context,

System.Threading.CancellationToken cancellationToken)
{
var user = context.ActionContext.ControllerContext.RequestContext.Principal;

if (null != user && user.Identity.IsAuthenticated)

return Task.Factory.StartNew(() => { }, cancellationToken);

var parameter = string.Format("realm=\"{0}\"", context.Request.RequestUri.DnsSafeHost);

var challenge=new AuthenticationHeaderValue(
"Basic",parameter);
context.Result=new UnauthorizedResult(new[]{challenge},
context.Request);

return Task.FromResult<object>(null);

}
}

转载于:https://www.cnblogs.com/zhijianblogs/p/5325580.html

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

上一篇:P1280 尼克的任务
下一篇:ASP.NET知识点(二):数据访问层的基础[SQLHelper]

发表评论

最新留言

很好
[***.229.124.182]2024年03月06日 07时35分24秒

关于作者

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

推荐文章

mysql整体会滚_滚mysql 2019-04-21
向mysql数据库中添加批量数据类型_使用JDBC在MySQL数据库中快速批量插入数据 2019-04-21
最全的mysql 5.7.13_最全的mysql 5.7.13 安装配置方法图文教程(linux) 强烈推荐! 2019-04-21
mssql连接mysql数据库文件_在本地 怎么远程连接MSSQL数据库 2019-04-21
mssql 远程无法连接mysql_解决SQLServer远程连接失败的问题 2019-04-21
linux mysql c++编程_Linux下进行MYSQL的C++编程起步手记 2019-04-21
Maria数据库怎么复制到mysql_MySQL、MariaDB数据库的AB复制配置过程 2019-04-21
mysql5.6 icp mrr bak_【mysql】关于ICP、MRR、BKA等特性 2019-04-21
mysql utf8跟utf8mb4_MySQL utf8 和 utf8mb4 的区别 2019-04-21
docker mysql开机自启动_Docker学习4-学会如何让容器开机自启服务【坑】 2019-04-21
在mysql中删除表正确的是什么_在MySQL中删除表的操作教程 2019-04-21
mysql有3个共同好友_共同好友mysql 2019-04-21
代理查询 mysql_查询数据库代理设置 2019-04-21
mysql dif_mysqldiff实现MySQL数据表比较 2019-04-21
mysql 允许其他主机访问权限_允许其他主机访问本机MySQL 2019-04-21
druid不能close mysql连接_alibaba druid mysql连接问题 2019-04-21
mysql 设置按天分表_MySQL 优化实战记录 2019-04-21
java连接mysql 不推荐_java连接mysql 2019-04-21
mysql数据库 quota_shell脚本抓取用户存储quota写道mysql并展现到grafana面板 2019-04-21
idea测试连接mysql报错08001_IDEA连接MySQL错误 2019-04-21