.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 ...
随机推荐
- Ubuntu找不到stdio.h等头文件_安装c库_build-essential安装失败解决
最近安装的Ubuntu1804系统,vim.gcc都是现安的,用gcc编译时出现找不到头文件情况: 于是百度. 原来linux类的操作系统上面开发程序,光有了gcc 是不行的,它还需要一个 build ...
- Redis两种持久化策略分析
Redis专题地址:https://www.cnblogs.com/hello-shf/category/1615909.html SpringBoot读源码系列:https://www.cnblog ...
- [译]C# 7系列,Part 1: Value Tuples 值元组
Mark Zhou写了很不错的一系列介绍C# 7的文章,虽然是2年多年前发布的,不过对于不熟悉C# 7特性的同学来说,仍然有很高的阅读价值. 原文:https://blogs.msdn.microso ...
- 阅读webpack代码笔记:antd-layout的webpack.config.prod.js
'use strict'; const autoprefixer = require('autoprefixer');//自动补全css前缀 const path = require('path'); ...
- 面试连环炮系列(七):HashMap的put操作做了什么
HashMap的put操作做了什么? HashMap的是由数组和链表构成的,JDK7之后加入了红黑树处理哈希冲突.put操作的步骤是这样的: 根据key值计算出哈希值作为数组下标.如果数组的这个位置是 ...
- 关联mysql失败_Server returns invalid timezone. Go to 'Advanced' tab and set 'serverTimezon'
关联mysql失败_Server returns invalid timezone. Go to ‘Advanced’ tab and set ‘serverTimezon’ 时区错误,MySQL默认 ...
- LinuxProbe小结
1.修改主机名: /etc/hostname 2.配置 yum 软件仓库: (1)进入到 /etc/yum.repos.d/目录下,创建一个linuxprobe.repo的新文件(文件名称任意,结尾必 ...
- VM虚拟机与本地网络互通配置
一.设置虚拟机网络 1. 查看虚拟机网络NAT设置(VMnet8) 2. 设置虚拟机网络适配器为NAT模式 三.设置本机VMnet8网络属性 三.设置Linux网络属性 1. 查看 ip addr 2 ...
- C# -- 优先获取电脑C盘之外的磁盘来保存数据
C# -- 优先获取电脑C盘之外的磁盘来保存数据 1. 优先获取电脑C盘之外的磁盘来保存数据.没有其他盘则使用C盘. public string GetSaveDataDiskPath() { str ...
- LinkedHashMap源码学习
描述 可以按照添加元素的顺序对元素进行迭代的HashMap的子类. 注意,上面说的是加元素的顺序.也就是说,更新元素时,是不会影响遍历结构的的.除非设置参数accessOrder为true,将更新元素 ...