在身份认证中,如果某个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扩展的更多相关文章

  1. asp.net core 自定义401和异常显示内容(JWT认证、Cookie Base认证失败显示内容)

    asp.net core 2.0使用JWT认证园子里已经有挺多帖子了,但开发中发现认证未授权情况下返回的401状态码是没有任何信息的,业务中可能有需要返回一串错误的Json信息.在这里我分享一个自定义 ...

  2. ASP.NET Core Identity 实战(3)认证过程

    如果你没接触过旧版Asp.Net Mvc中的 Authorize 或者 Cookie登陆,那么你一定会疑惑 认证这个名词,这太正式了,这到底代表这什么? 获取资源之前得先过两道关卡Authentica ...

  3. Asp.Net Core 2.0 项目实战(10) 基于cookie登录授权认证并实现前台会员、后台管理员同时登录

    1.登录的实现 登录功能实现起来有哪些常用的方式,大家首先想到的肯定是cookie或session或cookie+session,当然还有其他模式,今天主要探讨一下在Asp.net core 2.0下 ...

  4. 理解ASP.NET Core - 基于Cookie的身份认证(Authentication)

    注:本文隶属于<理解ASP.NET Core>系列文章,请查看置顶博客或点击此处查看全文目录 概述 通常,身份认证(Authentication)和授权(Authorization)都会放 ...

  5. 在 ASP.NET Core 应用中使用 Cookie 进行身份认证

    Overview 身份认证是网站最基本的功能,最近因为业务部门的一个需求,需要对一个已经存在很久的小工具网站进行改造,因为在逐步的将一些离散的系统迁移至 .NET Core,所以趁这个机会将这个老的 ...

  6. ASP.NET CORE中使用Cookie身份认证

    大家在使用ASP.NET的时候一定都用过FormsAuthentication做登录用户的身份认证,FormsAuthentication的核心就是Cookie,ASP.NET会将用户名存储在Cook ...

  7. ASP.NET Core 基于JWT的认证(二)

    ASP.NET Core 基于JWT的认证(二) 上一节我们对 Jwt 的一些基础知识进行了一个简单的介绍,这一节我们将详细的讲解,本次我们将详细的介绍一下 Jwt在 .Net Core 上的实际运用 ...

  8. ASP.NET Core 基于JWT的认证(一)

    ASP.NET Core 基于JWT的认证(一) Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计 ...

  9. NET Core 2.0使用Cookie认证实现SSO单点登录

    NET Core 2.0使用Cookie认证实现SSO单点登录 之前写了一个使用ASP.NET MVC实现SSO登录的Demo,https://github.com/bidianqing/SSO.Sa ...

随机推荐

  1. Python基础-day01-4

    多文件项目的演练 开发 项目 就是开发一个 专门解决一个复杂业务功能的软件 通常每 一个项目 就具有一个 独立专属的目录,用于保存 所有和项目相关的文件 一个项目通常会包含 很多源文件 目标 在项目中 ...

  2. [译]C# 7系列,Part 1: Value Tuples 值元组

    Mark Zhou写了很不错的一系列介绍C# 7的文章,虽然是2年多年前发布的,不过对于不熟悉C# 7特性的同学来说,仍然有很高的阅读价值. 原文:https://blogs.msdn.microso ...

  3. Winform中实现仿XP系统的任务栏菜单效果(附代码下载)

    场景 效果 注: 博客主页: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 霸道的程序猿 获取编程相关电子书.教程推送与免费下载. 实现 新建一个Fo ...

  4. 集合框架关于<list接口><map接口>的运用

    集合: 集合就是一个容器,他可以存储对象,我们说集合就是一个可变的数组 集合框架特点 1.list和set集合同时实现了collection接口 2.set集合存储唯一,无序的对象. 3.list 存 ...

  5. SAP QA32试图做UD,系统报错-工厂 BTYC中的 QM 基选设置需要维护

    SAP QA32 试图做UD,系统报错 - 工厂 BTYC 中的 QM 基选设置需要维护 - 检验批 10000062593,试图做使用决策,系统报错, 工厂 BTYC 中的 QM 基选设置需要维护 ...

  6. Sqlite—锁机制

    https://blog.csdn.net/zhangsheng_1992/article/details/52598396 https://blog.csdn.net/xiyangyang8110/ ...

  7. windows 安装xps查看器; windows 10 安装 xps viewer

    最近发现windows 默认是没有xps 查看器的,需要自己手动添加: 安装完成后,即可使用: 参考链接:https://www.windowscentral.com/how-get-xps-view ...

  8. Jsonp的js实现,跨域请求,同源策略机制

    Jsonp的js实现,跨域请求,同源策略机制1.跨域请求:请求URL的协议,域名,端口三者之间任意一个与当前页面地址不同即为跨域 存在跨域的情况: 网络协议不同,端口不通,域名不同,子域名不同,域名和 ...

  9. 【编码】彻底弄懂ASCII、Unicode、UTF-8之间的关系

    计算机中的所有字符,说到底都是用二进制的0.1的排列组合来表示的,因此就需要有一个规范,来枚举规定每个字符对应哪个0.1的排列组合,这样的规范就是字符集. ASCII 全称是“美国信息交换标准码”(A ...

  10. UE4入门学习笔记开篇

    做了3年的Unity, 现在开始转入到做UE4,一来就进入一个超大项目组中学习,度过了最初2个月的生涩和紧张后,现在准备开始慢慢总结,慢慢学习,逐步深入理解和研究UE. 做了3年的游戏开发后,个人感悟 ...