.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 ...
随机推荐
- UWP 更强大的文件获取能力
默认情况下,通用 Windows 平台 (UWP) 应用可以访问特定文件系统位置. 应用也可以通过文件选取器或通过声明功能访问其他位置. 在创建新的应用时,默认情况下你可以访问以下文件系统位置: 1. ...
- Spring IoC容器与应用上下文的设计与实现
一.前言 写这篇博文的主要目的如下: 通过相关类和接口分析IoC容器到底长什么样. 阐述笔者对Spring上下文和容器的理解. 介绍重要的类辅助理解SpringBoot的启动流程. 二.Spring ...
- 3、看源码MVC中的Controllr的Json方法
无论ViewResult还是JsonResult都继承ActionResult,ActionResult里只有一个方法ExecuteResult 1.Controllr的Json方法 实际上是new ...
- vscode 同步扩展插件
第一步: 在 VSCode 中,安装用于同步配置的插件 settings sync 第二步:将 VSCode 配置上传到 GitHub 完成这一步需要 GitHub token 和 GitHu ...
- AI: Web: 2 Vulnhub Walkthrough
靶机下载链接: https://www.vulnhub.com/entry/ai-web-2,357 主机端口扫描: 尝试SQL注入,未发现有注入漏洞,就注册创建于一账户 http://10.10.2 ...
- SpringBoot+idea搭建微服务简化流程
作者:个人微信公众号:程序猿的月光宝盒 1.新建普通maven工程 2.在父级pom中按需修改 3.删除父级src目录 4.创建公共模块common,里面只有service接口和实体类 5.构建微服务 ...
- python yield关键词使用总结
python yield关键词使用总结 by:授客 QQ:1033553122 测试环境 win10 python 3.5 yield功能简介 简单来说,yield 的作用就是把一个函数变成一个 ge ...
- 20190608_浅谈go&java差异(三)
20190608_浅谈go&java差异(三) 转载请注明出处https://www.cnblogs.com/funnyzpc/p/10990703.html 第三节内容概览 多线程通讯(线程 ...
- jq实现回车键事件
我们写系统的时候常常因为要点击显得很麻烦,习惯了回车键完成一些东西. 接下来就直接上代码吧.jq实现回车键事件 keyDowm: () => { $("body").keyd ...
- MySQL数据库~~~~~存储引擎
1. InnoDB InnoDB引擎特点: 1.支持事务:支持4个事务隔离界别,支持多版本读. 2.行级锁定(更新时一般是锁定当前行):通过索引实现,全表扫描仍然会是表锁,注意间隙锁的影响. 3.读写 ...