在身份认证中,如果某个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. UWP 更强大的文件获取能力

    默认情况下,通用 Windows 平台 (UWP) 应用可以访问特定文件系统位置. 应用也可以通过文件选取器或通过声明功能访问其他位置. 在创建新的应用时,默认情况下你可以访问以下文件系统位置: 1. ...

  2. Spring IoC容器与应用上下文的设计与实现

    一.前言 写这篇博文的主要目的如下: 通过相关类和接口分析IoC容器到底长什么样. 阐述笔者对Spring上下文和容器的理解. 介绍重要的类辅助理解SpringBoot的启动流程. 二.Spring ...

  3. 3、看源码MVC中的Controllr的Json方法

    无论ViewResult还是JsonResult都继承ActionResult,ActionResult里只有一个方法ExecuteResult 1.Controllr的Json方法 实际上是new ...

  4. vscode 同步扩展插件

    第一步: 在 VSCode 中,安装用于同步配置的插件 settings sync     第二步:将 VSCode 配置上传到 GitHub 完成这一步需要 GitHub token 和 GitHu ...

  5. AI: Web: 2 Vulnhub Walkthrough

    靶机下载链接: https://www.vulnhub.com/entry/ai-web-2,357 主机端口扫描: 尝试SQL注入,未发现有注入漏洞,就注册创建于一账户 http://10.10.2 ...

  6. SpringBoot+idea搭建微服务简化流程

    作者:个人微信公众号:程序猿的月光宝盒 1.新建普通maven工程 2.在父级pom中按需修改 3.删除父级src目录 4.创建公共模块common,里面只有service接口和实体类 5.构建微服务 ...

  7. python yield关键词使用总结

    python yield关键词使用总结 by:授客 QQ:1033553122 测试环境 win10 python 3.5 yield功能简介 简单来说,yield 的作用就是把一个函数变成一个 ge ...

  8. 20190608_浅谈go&java差异(三)

    20190608_浅谈go&java差异(三) 转载请注明出处https://www.cnblogs.com/funnyzpc/p/10990703.html 第三节内容概览 多线程通讯(线程 ...

  9. jq实现回车键事件

    我们写系统的时候常常因为要点击显得很麻烦,习惯了回车键完成一些东西. 接下来就直接上代码吧.jq实现回车键事件 keyDowm: () => { $("body").keyd ...

  10. MySQL数据库~~~~~存储引擎

    1. InnoDB InnoDB引擎特点: 1.支持事务:支持4个事务隔离界别,支持多版本读. 2.行级锁定(更新时一般是锁定当前行):通过索引实现,全表扫描仍然会是表锁,注意间隙锁的影响. 3.读写 ...