.Net Core权限认证基于Cookie的认证&授权.Scheme、Policy扩展
在身份认证中,如果某个Action需要权限才能访问,最开始的想法就是,哪个Action需要权限才能访问,我们写个特性标注到上面即可,[TypeFilter(typeof(CustomAuthorizeActionFilterAttribute))]
/// <summary>
/// 这是一个Action的Filter` 但是用作权限验证
/// </summary>
public class CustomAuthorizeActionFilterAttribute : Attribute, IActionFilter
{
private ILogger<CustomAuthorizeActionFilterAttribute> _logger = null;
public CustomAuthorizeActionFilterAttribute(ILogger<CustomAuthorizeActionFilterAttribute> logger)
{
this._logger = logger;
} public void OnActionExecuting(ActionExecutingContext context)
{
//取出Session
var strUser = context.HttpContext.Session.GetString("CurrentUser");
if (!string.IsNullOrWhiteSpace(strUser))
{
CurrentUser currentUser = Newtonsoft.Json.JsonConvert.DeserializeObject<CurrentUser>(strUser);
_logger.LogDebug($"userName is {currentUser.Name}");
}
else
{
context.Result = new RedirectResult("~/Fourth/Login");
} }
public void OnActionExecuted(ActionExecutedContext context)
{
//context.HttpContext.Response.WriteAsync("ActionFilter Executed!");
Console.WriteLine("ActionFilter Executed!");
//this._logger.LogDebug("ActionFilter Executed!");
} }
当然了,要先在服务里面使用Session的服务==》services.AddSession();
但是这样不好。.Net Core框架下,有一个特性Authorize,当我们需要使用的时候,在某个Action上面标注即可
[Authorize]
public IActionResult Center()
{
return Content("Center");
}
我们来运行看一下,会报异常

因为我们没有使用服务,在.Net Core下面,是默认不启用授权过滤器的。这也是.Net Core框架的一个好处,我们需要的时候才进行使用。框架做的少,更轻。
下面我们在服务里面使用授权过滤器的服务
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).
AddCookie(CookieAuthenticationDefaults.AuthenticationScheme,
o =>
{
o.LoginPath = new PathString("/Home/Login");
});
再次浏览刚才的页面,这样就会请求到登录页面,会把刚才请求的页面当做一个参数

当然也要使用app.UseAuthentication();这个中间件。
在.Net Core里面,保存登录状态,也是通过Cookie的方式。使用ClaimsIdentity与ClaimsPrincipal
public ActionResult Login(string name, string password)
{
this._ilogger.LogDebug($"{name} {password} 登陆系统");
#region 这里应该是要到数据库中查询验证的
CurrentUser currentUser = new CurrentUser()
{
Id = ,
Name = "Bingle",
Account = "Administrator",
Password = "",
Email = "415473422@qq.com",
LoginTime = DateTime.Now,
Role = name.Equals("Bingle") ? "Admin" : "User"
};
#endregion #region cookie
{
////就很像一个CurrentUser,转成一个claimIdentity
var claimIdentity = new ClaimsIdentity("Cookie");
claimIdentity.AddClaim(new Claim(ClaimTypes.NameIdentifier, currentUser.Id.ToString()));
claimIdentity.AddClaim(new Claim(ClaimTypes.Name, currentUser.Name));
claimIdentity.AddClaim(new Claim(ClaimTypes.Email, currentUser.Email));
claimIdentity.AddClaim(new Claim(ClaimTypes.Role, currentUser.Role));
claimIdentity.AddClaim(new Claim(ClaimTypes.Sid, currentUser.Id.ToString()));
var claimsPrincipal = new ClaimsPrincipal(claimIdentity);
base.HttpContext.SignInAsync(claimsPrincipal).Wait();//不就是写到cookie
}
#endregion return View();
}
再次进行登录,我们就可以看到这样一个Cookie

在这之后,我们再去访问Genter页面,发现还是和之前返回的结果一样,还是访问不到。这是为什么呢?是因为我们在Action上面打的标签[Authorize],什么都没给,我们做下修改
[Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)]
public IActionResult Center()
{
return Content("Center");
}
现在我们再次进行访问,发现就可以访问成功了

通过User.FindFirstValue(ClaimTypes.Sid);这种方式,可以获取到我们存入的值。
Scheme、Policy扩展
Scheme
#region 设置自己的schema的handler
services.AddAuthenticationCore(options => options.AddScheme<MyHandler>("myScheme", "demo myScheme"));
#endregion
#region Schame 验证 services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;// "Richard";//
})
.AddCookie(options =>
{
options.LoginPath = new PathString("/Fourth/Login");// 这里指定如果验证不通过就跳转到这个页面中去
options.ClaimsIssuer = "Cookie";
});
MyHandler类:
/// <summary>
/// 自定义的handler
/// 通常会提供一个统一的认证中心,负责证书的颁发及销毁(登入和登出),而其它服务只用来验证证书,并用不到SingIn/SingOut。
/// </summary>
public class MyHandler : IAuthenticationHandler, IAuthenticationSignInHandler, IAuthenticationSignOutHandler
{
public AuthenticationScheme Scheme { get; private set; }
protected HttpContext Context { get; private set; } public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
{
Scheme = scheme;
Context = context;
return Task.CompletedTask;
} /// <summary>
/// 认证
/// </summary>
/// <returns></returns>
public async Task<AuthenticateResult> AuthenticateAsync()
{
var cookie = Context.Request.Cookies["myCookie"];
if (string.IsNullOrEmpty(cookie))
{
return AuthenticateResult.NoResult();
}
return AuthenticateResult.Success(this.Deserialize(cookie));
} /// <summary>
/// 没有登录 要求 登录
/// </summary>
/// <param name="properties"></param>
/// <returns></returns>
public Task ChallengeAsync(AuthenticationProperties properties)
{
Context.Response.Redirect("/login");
return Task.CompletedTask;
} /// <summary>
/// 没权限
/// </summary>
/// <param name="properties"></param>
/// <returns></returns>
public Task ForbidAsync(AuthenticationProperties properties)
{
Context.Response.StatusCode = ;
return Task.CompletedTask;
} /// <summary>
/// 登录
/// </summary>
/// <param name="user"></param>
/// <param name="properties"></param>
/// <returns></returns>
public Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties properties)
{
var ticket = new AuthenticationTicket(user, properties, Scheme.Name);
Context.Response.Cookies.Append("myCookie", this.Serialize(ticket));
return Task.CompletedTask;
} /// <summary>
/// 退出
/// </summary>
/// <param name="properties"></param>
/// <returns></returns>
public Task SignOutAsync(AuthenticationProperties properties)
{
Context.Response.Cookies.Delete("myCookie");
return Task.CompletedTask;
}
private AuthenticationTicket Deserialize(string content)
{
byte[] byteTicket = System.Text.Encoding.Default.GetBytes(content);
return TicketSerializer.Default.Deserialize(byteTicket);
} private string Serialize(AuthenticationTicket ticket)
{ //需要引入 Microsoft.AspNetCore.Authentication byte[] byteTicket = TicketSerializer.Default.Serialize(ticket);
return Encoding.Default.GetString(byteTicket);
}
}
Policy
#region 支持 policy 认证授权的服务 // 指定通过策略验证的策略列
services.AddSingleton<IAuthorizationHandler, AdvancedRequirement>(); services.AddAuthorization(options =>
{
//AdvancedRequirement可以理解为一个别名
options.AddPolicy("AdvancedRequirement", policy =>
{
policy.AddRequirements(new NameAuthorizationRequirement(""));
});
}).AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.LoginPath = new PathString("/Fourth/Login");
options.ClaimsIssuer = "Cookie";
}); #endregion
AdvancedRequirement类:
/// <summary>
/// Policy 的策略 或者是规则
/// </summary>
public class AdvancedRequirement : AuthorizationHandler<NameAuthorizationRequirement>, IAuthorizationRequirement
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, NameAuthorizationRequirement requirement)
{
// 这里可以把用户信息获取到以后通过数据库进行验证
// 这里就可以做一个规则验证
// 也可以通过配置文件来验证
if (context.User != null && context.User.HasClaim(c => c.Type == ClaimTypes.Sid))
{
string sid = context.User.FindFirst(c => c.Type == ClaimTypes.Sid).Value;
if (!sid.Equals(requirement.RequiredName))
{
context.Succeed(requirement);
}
} return Task.CompletedTask;
}
}
还需要在Configure方法中对中间件进行使用
app.UseSession();
app.UseCookiePolicy(); //
app.UseAuthentication(); // 标识在当前系统中使用这个权限认证
总结:
在.Net Framwork环境授权一般来说是这个样子的,在登录的时候写入Session,在需要控制权限的方法上标机一个权限特性,实现在方法执行前对Session进行判断,如果有Session,就有权限。但是这种方式比较局限。
.Net Core下的权限认证,来自于AuthenticationHttpContextExtensions扩展。
6大方法,可以自行扩展这6个方法:需要自定义一个handler,handler需要继承实现IAuthenticationHandler,IAuthenticationSignInHandler,IAuthenticationSignOutHandler。分别实现6个方法,需要制定在Core中使用。services.AddAuthenticationCore(options => options.AddScheme<MyHandler>("myScheme", "demo myScheme"));
如果使用了Sechme验证,验证不通过的时候,就默认跳转到Account/Login?ReturnUrl=......。权限验证来自于IAuthentizeData:AuthenticationSchemes Policy Roles。权限验证支持Action、控制器、全局三种注册方式。
.Net Core权限认证基于Cookie的认证&授权.Scheme、Policy扩展的更多相关文章
- asp.net core 自定义401和异常显示内容(JWT认证、Cookie Base认证失败显示内容)
asp.net core 2.0使用JWT认证园子里已经有挺多帖子了,但开发中发现认证未授权情况下返回的401状态码是没有任何信息的,业务中可能有需要返回一串错误的Json信息.在这里我分享一个自定义 ...
- ASP.NET Core Identity 实战(3)认证过程
如果你没接触过旧版Asp.Net Mvc中的 Authorize 或者 Cookie登陆,那么你一定会疑惑 认证这个名词,这太正式了,这到底代表这什么? 获取资源之前得先过两道关卡Authentica ...
- Asp.Net Core 2.0 项目实战(10) 基于cookie登录授权认证并实现前台会员、后台管理员同时登录
1.登录的实现 登录功能实现起来有哪些常用的方式,大家首先想到的肯定是cookie或session或cookie+session,当然还有其他模式,今天主要探讨一下在Asp.net core 2.0下 ...
- 理解ASP.NET Core - 基于Cookie的身份认证(Authentication)
注:本文隶属于<理解ASP.NET Core>系列文章,请查看置顶博客或点击此处查看全文目录 概述 通常,身份认证(Authentication)和授权(Authorization)都会放 ...
- 在 ASP.NET Core 应用中使用 Cookie 进行身份认证
Overview 身份认证是网站最基本的功能,最近因为业务部门的一个需求,需要对一个已经存在很久的小工具网站进行改造,因为在逐步的将一些离散的系统迁移至 .NET Core,所以趁这个机会将这个老的 ...
- ASP.NET CORE中使用Cookie身份认证
大家在使用ASP.NET的时候一定都用过FormsAuthentication做登录用户的身份认证,FormsAuthentication的核心就是Cookie,ASP.NET会将用户名存储在Cook ...
- ASP.NET Core 基于JWT的认证(二)
ASP.NET Core 基于JWT的认证(二) 上一节我们对 Jwt 的一些基础知识进行了一个简单的介绍,这一节我们将详细的讲解,本次我们将详细的介绍一下 Jwt在 .Net Core 上的实际运用 ...
- ASP.NET Core 基于JWT的认证(一)
ASP.NET Core 基于JWT的认证(一) Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计 ...
- NET Core 2.0使用Cookie认证实现SSO单点登录
NET Core 2.0使用Cookie认证实现SSO单点登录 之前写了一个使用ASP.NET MVC实现SSO登录的Demo,https://github.com/bidianqing/SSO.Sa ...
随机推荐
- Python基础-day01-4
多文件项目的演练 开发 项目 就是开发一个 专门解决一个复杂业务功能的软件 通常每 一个项目 就具有一个 独立专属的目录,用于保存 所有和项目相关的文件 一个项目通常会包含 很多源文件 目标 在项目中 ...
- [译]C# 7系列,Part 1: Value Tuples 值元组
Mark Zhou写了很不错的一系列介绍C# 7的文章,虽然是2年多年前发布的,不过对于不熟悉C# 7特性的同学来说,仍然有很高的阅读价值. 原文:https://blogs.msdn.microso ...
- Winform中实现仿XP系统的任务栏菜单效果(附代码下载)
场景 效果 注: 博客主页: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 霸道的程序猿 获取编程相关电子书.教程推送与免费下载. 实现 新建一个Fo ...
- 集合框架关于<list接口><map接口>的运用
集合: 集合就是一个容器,他可以存储对象,我们说集合就是一个可变的数组 集合框架特点 1.list和set集合同时实现了collection接口 2.set集合存储唯一,无序的对象. 3.list 存 ...
- SAP QA32试图做UD,系统报错-工厂 BTYC中的 QM 基选设置需要维护
SAP QA32 试图做UD,系统报错 - 工厂 BTYC 中的 QM 基选设置需要维护 - 检验批 10000062593,试图做使用决策,系统报错, 工厂 BTYC 中的 QM 基选设置需要维护 ...
- Sqlite—锁机制
https://blog.csdn.net/zhangsheng_1992/article/details/52598396 https://blog.csdn.net/xiyangyang8110/ ...
- windows 安装xps查看器; windows 10 安装 xps viewer
最近发现windows 默认是没有xps 查看器的,需要自己手动添加: 安装完成后,即可使用: 参考链接:https://www.windowscentral.com/how-get-xps-view ...
- Jsonp的js实现,跨域请求,同源策略机制
Jsonp的js实现,跨域请求,同源策略机制1.跨域请求:请求URL的协议,域名,端口三者之间任意一个与当前页面地址不同即为跨域 存在跨域的情况: 网络协议不同,端口不通,域名不同,子域名不同,域名和 ...
- 【编码】彻底弄懂ASCII、Unicode、UTF-8之间的关系
计算机中的所有字符,说到底都是用二进制的0.1的排列组合来表示的,因此就需要有一个规范,来枚举规定每个字符对应哪个0.1的排列组合,这样的规范就是字符集. ASCII 全称是“美国信息交换标准码”(A ...
- UE4入门学习笔记开篇
做了3年的Unity, 现在开始转入到做UE4,一来就进入一个超大项目组中学习,度过了最初2个月的生涩和紧张后,现在准备开始慢慢总结,慢慢学习,逐步深入理解和研究UE. 做了3年的游戏开发后,个人感悟 ...