.NET core3.1使用cookie进行身份认证
一个系统,用户身份认证少不了,ASP.NET Core提供完整的解决方案Identity,用户创建和维护登录名;也提供能cookie和JwtBearer认证方案,当然你可以使用第三方认证Oauth、openId。项目没有采用前后端分离,是一个标准的mvc项目,所以本文采用系统提供的cookie认证 记录一下简单认证流程,(1)使用用户账号密码进行登录,验证合法登录(2)确认合法身份之后,会颁发一个认证票据(加密)会携带与该用户相关的身份、权限以及其他信息。(3)退出。
主要会使用Microsoft.AspNetCore.Authentication.Abstractions包中 AuthenticationHttpContextExtensions类,它是基于HttpContext上公开身认证的扩展法:
方法 |
描述 |
---|---|
SignInAsync |
登录用户.用户登录成功后颁发一个证书(加密的用户凭证,这个凭证放入Cookie中),用来标识用户的身份 |
SignOutAsync |
注销退出.清除Cookie |
GetTokenAsync |
用来获取 AuthenticationProperties 中保存的额外信息 |
ForbidAsync |
通知用户权限不足,如果是ajax请求返回403状态码,不是ajax请求跳转指定的url |
ChallengeAsync |
通知用户需要登录。在默认实现类AuthenticationHandler中,返回401 |
AuthenticateAsync |
验证在 SignInAsync 中颁发的证书,并返回一个 AuthenticateResult 对象,表示用户的身份。 |
登录创建一个cookie认证
这里涉及几个对象:Claim声明常常代表,认证用户身份的元数据信息,比如手机号、邮箱、用户名等等。ClaimsIdentity声明主体,代表一个认证用户的身份证,当然包含声明的集合。ClaimsPrincipal身份证持有者。
流程:创建一个包含用户信息的 cookie需要构造一个ClaimsPrincipal。将序列化用户信息并将其存储在中 cookie 。
用必要的 Claim来构造一个ClaimsIdentity,然后调用 SignInAsync 来登录用户。
public async Task<Result> UserLogin([FromForm] UserLoginInput input)
{
//登录逻辑
var model = userService.UserLogin(input);
//1.创建cookie 保存用户信息,使用claim。将序列化用户信息并将其存储在cookie中
var claims = new List<Claim>()
{
new Claim(ClaimTypes.MobilePhone,model.Mobile),
new Claim(ClaimTypes.Name,model.UserName),
new Claim("Id",model.SysNo.ToString())
};
//2.创建声明主题 指定认证方式 这里使用cookie
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
//3.配置认证属性 比如过期时间,是否持久化。。。。
var authProperties = new AuthenticationProperties
{
//AllowRefresh = <bool>,
// Refreshing the authentication session should be allowed.
//ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(10),
// The time at which the authentication ticket expires. A
// value set here overrides the ExpireTimeSpan option of
// CookieAuthenticationOptions set with AddCookie.
//IsPersistent = true,
//持久化 ,比如 登录的时候 勾选记住我 复选框
//IssuedUtc = <DateTimeOffset>,
//绝对cookie过期
//RedirectUri = <string>
// The full path or absolute URI to be used as an http
// redirect response value.
};
//4.登录
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), authProperties);
return Result.ResponseSuccess();
}
SignInAsync 创建一个加密的 cookie ,并将其添加到当前响应中。
退出
退出很简单,主要用户清除cookie
HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
获取认证信息
登录之后,我们通常会获取一些声明中的信息,可以使用 HttpContext.User 将会返回一个ClaimsPrincipal对象
ClaimsPrincipal principal = HttpContext.User;
if (null != principal)
{
foreach (Claim claim in principal.Claims)
{
var ii = "CLAIM TYPE: " + claim.Type + "; CLAIM VALUE: " + claim.Value + "</br>";
}
}
统一处理获取到的信息,赋值UserViewModel实例CurrentLoginUser
public class BaseController : Controller
{
public UserViewModel CurrentLoginUser
{
get
{
var principal = HttpContext.User;
if (principal != null)
{
return new UserViewModel()
{
UserName = principal.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Name)?.Value,
Mobile = principal.Claims.FirstOrDefault(x => x.Type == ClaimTypes.MobilePhone)?.Value,
SysNo = new Guid(principal.Claims.FirstOrDefault(x => x.Type == "Id")?.Value ?? Guid.Empty.ToString())
};
}
return null;
}
}
使用
var userId = CurrentLoginUser.SysNo;
startup类配置
在ConfigureServices方法添加
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.LoginPath =new PathString("/User/Login");
});
在Configure方法添加
application.UseAuthentication();
application.UseAuthorization();
参考:
https://docs.microsoft.com/zh-cn/aspnet/core/security/authentication/cookie?view=aspnetcore-3.1
- .net异步性能测试(包括ASP.NET MVC WebAPI异步方法)
- Java 8的函数式编程学习
- 在C++中反射调用.NET(一) 反射调用第一个.NET类的方法
- QuickPager分页控件,最简单的设置代码
- Java中有关Null的9问题
- 在C++中反射调用.NET(二) 定义数据接口 绑定委托方法 使用SOD DTO 对象 将.NET对象转换到C++结构体为何不使用序列化的问题
- Java阻塞队列线程集控制的实现方法
- 【自然框架】QuickPager分页控件,新增一种分页方式——伪URL分页(Postback版)
- 我们的漏洞Webug 3.0中级进阶攻略(上)
- 【自然框架】QuickPager分页控件的总体介绍和在线演示
- 在C++中反射调用.NET(三) 使用非泛型集合的委托方法C++中的列表对象list C++传递集合数据给.NET创建泛型List实例反射静态方法反射调用索引器当委托遇到协变和逆变C++/CLI
- 如何使用树莓派自制网络监视器
- 利用雅虎小型企业服务平台的目录遍历漏洞查看客户的信用卡信息
- 【自然框架】QuickPager asp.net 分页控件的Ajax分页方式。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 多线程基础(七):关于HotSpot中notify方法不具备随机性的证明
- Day18:二叉树的镜像
- ksubdomain 无状态域名爆破工具
- Day19:顺时针打印矩阵
- 疑似 KimsukyAPT 组织最新攻击活动样本分析
- 查找被删除但仍然占据磁盘的文件
- WPF 获取本机所有字体拿到每个字符的宽度和高度
- WPF 自己封装 Skia 差量绘制控件
- C# dotnet 使用 OpenXml 解析 Word 文件
- Day20:包含min函数的栈
- No module named ‘SerialClient‘和Cannot import package : rosserial_arduino
- 提升开发效率N倍的20+命令行神器!(附 demo)
- Java反射原理
- 【每日一题】46. Permutations
- 免费下论文的10个方法