首页 > 编程语言 >转:ASP.NET Core Identity 系列之四

转:ASP.NET Core Identity 系列之四

时间:2023-06-21 16:06:35浏览次数:43  
标签:Core ASP 登录 用户 public 之四 Login login Identity

转自:https://mp.weixin.qq.com/s?__biz=MzA3NDM1MzIyMQ==&mid=2247486183&idx=1&sn=baeb28f24399a9b0203f33185e1399a6

这节我们主要介绍ASP.NET Core Identity认证,认证是决定用户是否能够成功登录应用程序的一个过程,用户通过提供自己的用户名和密码来证明他们自己是真实用户,当登录成功时, Identity 认证用户并且赋予访问ASP.NET Core 应用程序安全资源

1. ASP.NET Core Identity如何认证

我们创建ASP.NET Core Identity Authentication特性,允许对Identity User 进行认证,首先我们创建一个HomeController并修改Index Action 返回一个字符串到View
image

当我们运行应用程序时,我们可以没有任何限制的访问Index action,浏览器发送匿名请求(anonymous request) 到Home Controller 的Index 方法,这个匿名请求能访问应用程序Home Controller资源,因此我们能在浏览器上看到Hello消息

现在我们给Index Action增加认证,注意 Identity Authorization 和 Authentication 不同,Authorization 在 Authentication 之后,用户授权是指 Identity 授权一个用户访问应用程序资源

提交一个Identity authentication 非常容易,我们仅仅需要在Index 方法上提交一个 [Authorize] 特性,该特性位于在Microsoft.AspNetCore.Authorization命名空间,这将限制用户访问

现在我们运行app 将显示如下图
image

如下两点我们注意一下:

  • 在Index 方法上使用[Authorize]特性,用户访问Controller之前需要做认证
  • ASP.NET Core Identity 导航到 AccountControllerLogin 方法,这个是Identity默认登录页面,https://localhost:7296/Account/Login?ReturnUrl=%2Fhome%2Findex 这页面可以登录应用程序,我们稍后将构建这个页面

注意URL包含查询字符串变量叫ReturnUrl,包含%2F ,%2F是一个编码的字符,代表 / ,因此认证之后,用户将跳转到应用程序的主页面,在认证之前ReturnUrl包含一个用户访问的安全页面,一旦Identity认证成功将会跳转到ReturnUrl指定的安全页面

2. 修改Identity 中默认登录的URL

ASP.NET Core Identity 默认的登录地址是/Account/Login,可以通过如下代码改变默认的登录URL:

builder.Services.ConfigureApplicationCookie(opts => opts.LoginPath = "/Authenticate/Login");

我们在这里指定了新的登录地址/Authenticate/Login 例如: https://localhost:7296/Authenticate/Login

3. ASP.NET Core Identity 登录页面

为了实现Identity认证,我们将创建两个页面登录页面和退出,在登录页面中用户将输入用户名和密码进行认证,当用户退出时,用户点击logout按钮将退出登录

3.1 ASP.NET Core Identity 登录页面

在Models文件夹下创建Login文件,实体类中包含了三个属性,分别为Email、Password、ReturnUrl

public class Login
{
       [Required]
       [DisplayName("用户名")]
       public string Email { get; set; } = null!;
       [Required]
       [DisplayName("密码")]
       [DataType(DataType.Password)]
       public string Password { get; set; } = null!;
       public string? ReturnUrl { get; set; }
}

Email和Password是必填字段,用户在登录过程中必须输入这两个字段,Identity 默认登录地址是https://localhost:7296/Account/Login ,因此我们需要添加一个Account 控制器,并在该控制器中添加Login 方法

[Authorize]
public class AccountController : Controller
{
	private UserManager<AppUser> _userManager;
	private SignInManager<AppUser> _signInManager;
	public AccountController(UserManager<AppUser> userManager, SignInManager<AppUser> signInManager)
	{
		_userManager = userManager;
		_signInManager = signInManager;
	}

	[AllowAnonymous]
	public IActionResult Login(string returnUrl)
	{
		var login = new Login();
		login.ReturnUrl = returnUrl;
		return View(login);
	}
	[HttpPost]
	[AllowAnonymous]
	[ValidateAntiForgeryToken]
	public async Task<IActionResult> Login(Login login)
	{
		if (ModelState.IsValid)
		{
			var appUser = await _userManager.FindByEmailAsync(login.Email);
			if (appUser != null)
			{
				await _signInManager.SignOutAsync();
				var signInResult = await _signInManager.PasswordSignInAsync(appUser, login.Password, false, false);
				if (signInResult.Succeeded)
				{
					return Redirect(login.ReturnUrl ?? "/");
				}
			}
		}
		return View(login);
	}
}

我们在Controller上应用了 [Authorize] 特性,从而阻止匿名请求调用,在Login方法上添加了 [AllowAnonymous] 特性,允许匿名请求访问这个方法,login 方法必须允许匿名访问,否则我们永远无法登录,在 AccountController 构造函数中添加了 UserManager<AppUser>SignInManager<AppUser> 引用,UserManager<T> 主要负责管理Identity的用户,SignInManager<T> 主要负责Identity的认证过程

private UserManager<AppUser> _userManager;
private SignInManager<AppUser> _signInManager;
public AccountController(UserManager<AppUser> userManager, SignInManager<AppUser> signInManager)
{
     _userManager = userManager;
     _signInManager = signInManager;
}

下面我们添加一个Http Get版本的Login方法,在该方法上使用 [AllowAnonymous] 特性,可以匿名访问该方法,否则用户不能登录,这个action方法接受一个returnUrl的参数,该参数提供查询字符串,背后的原理:模型绑定将自动绑定该URL变量

[AllowAnonymous]
public IActionResult Login(string returnUrl)
{
    var login = new Login();
    login.ReturnUrl = returnUrl;
    return View(login);
}

下面我们添加一个Post版本的Login 方法,实际上认证用户的逻辑将在该方法中,代码如下:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(Login login)
{
    if (ModelState.IsValid)
    {
        var appUser = await _userManager.FindByEmailAsync(login.Email);
        if (appUser != null)
        {
            await _signInManager.SignOutAsync();
            var signInResult = await _signInManager.PasswordSignInAsync(appUser, login.Password, false, false);
            if (signInResult.Succeeded)
            {
                return Redirect(login.ReturnUrl ?? "/");
            }
        }
    }
    return View(login);
}

这个方法接受Login类型的参数,可以从用户登录表单中获取email和password的值,这个方法提供了两个特性:

  • [AllowAnonymous] 表示允许匿名用户访问
  • [ValidateAntiForgeryToken] 阻止CSRF攻击

首先我们根据 UserManagerFindByEmailAsync() 方法获取到用户信息,如果用户信息不为空,我们先退出登录,然后再调用 PasswordSignInAsync 进行登录,这个方法第三个参数和第四个参数分别设置成false,第三个参数表示我们不想持久化Cookie,第四个参数表示用户登录失败时是否锁定用户,该方法返回 SignInResult 登录结果对象,如果成功Succeeded返回true,否则返回false,登录成功之后,跳转到客户指定的URL

我们需要创建一个Login View的登录表单,这个视图是Identity登录页面,处理用户账户登录过程,我们在 Views/Account 下创建View页面,代码如下:

@model Login
@{
    ViewData["Title"] = "Login";
}
<div class="text-danger" asp-validation-summary="All"></div>
<form class="form-horizontal" role="form" method="post">
    <div class="mb-3 row">
        <label asp-for="Email" class="col-sm-1 control-label"></label>
        <div class="col-sm-11">
            <input asp-for="Email" class="form-control" />
        </div>
    </div>
    <div class="mb-3 row">
        <label asp-for="Password" class="col-sm-1 control-label"></label>
        <div class="col-sm-11">
            <input asp-for="Password" class="form-control" />
        </div>
    </div>
    <div class="mb-3 row">
        <div class="col-sm-11 offset-sm-1">
            <button type="submit" class="btn btn-primary">登录</button>
        </div>
    </div>
</form>

我们测试一下刚才创建的认证功能,注册了如下用户:

现在我们使用用户的邮箱和密码进行登陆,如果你没有任何用户信息,你可以通过 https://localhost:7296/Admin/Create 创建一个用户,运行应用程序输入用户名和密码:
image

我们可以使用 UserManager<T>GetUserAsyns() 方法类获取当前登录的用户信息并显示在View上:
image

编辑HomeController控制器,并获取User信息,将用户名传递到View

[Authorize]
public async Task<IActionResult> Index()
{
     var appUser = await _userManager.GetUserAsync(HttpContext.User);
     var message = "Hello " + appUser?.UserName;
     return View((object)message);
}

4. ASP.NET Core Identity 退出页面

Logout非常简单,我们调用SignInManager的SignOutAsync方法退出登录

public async Task<IActionResult> Logout()
{
   await _signInManager.SignOutAsync();
   return RedirectToAction("Index", "Home");
}

Logout方法将退出登录,并跳转到Home控制器的Index方法。User.Identity.IsAuthenticated 属性返回true表示用户已经登录,否则将返回 null,当用户成功登录应用程序时显示 Logout 链接。

运行应用程序并进行登录,登录之后将跳转到Home页我们能看到 Logout按钮,点击它可以退出 ASP.NET Core Identity,看下面图片:
image

5. ASP.NET Core Identity Cookie

ASP.NET Core Identity使用Cookie确定一个用户是否被认证,一旦这个用户被认证Cookie就会被创建并且存储在浏览器,每次HTTP请求时都会发送Cookie到服务器,当我们在浏览器中打开应用程序的任何URL,Identity就能确定请求来自哪个用户,Cookie名字为.AspNetCore.Identity.Application,我们可以在浏览器中查看到这个Cookie
image

5.1 Identity Cookie超时

我们可以使用IServiceCollection 的ConfigureApplicationCookie方法设置ASP.NET Core Identity Cookie超时时间

builder.Services.ConfigureApplicationCookie(
	opts =>
	{
		opts.LoginPath = "/Account/Login";
		//设置Cookie名称
		opts.Cookie.Name = ".AspNetCore.Identity.Application";
		//设置Cookie超时时间
		opts.ExpireTimeSpan = TimeSpan.FromMinutes(20);
		//设置滑动时间
		opts.SlidingExpiration = true;
	}
);

5.2 ASP.NET Core Identity Remember Me

我们创建一个Remember Me功能,帮助客户记住密码,我们只需要登录一次,Identity将创建一个持久Cookie在浏览器,我们在login.cshtml的页面添加一个type=checkbox的输入框

@model Login
@{
    ViewData["Title"] = "Login";
}
<div class="text-danger" asp-validation-summary="All"></div>
<form class="form-horizontal" role="form" method="post">
    <div class="mb-3 row">
        <label asp-for="Email" class="col-sm-1 control-label"></label>
        <div class="col-sm-11">
            <input asp-for="Email" class="form-control" />
        </div>
    </div>
    <div class="mb-3 row">
        <label asp-for="Password" class="col-sm-1 control-label"></label>
        <div class="col-sm-11">
            <input asp-for="Password" class="form-control" />
        </div>
    </div>
    <div class="mb-3 row">
        <label asp-for="RememberMe" class="col-sm-1 control-label"></label>
        <div class="col-sm-11">
            <input type="checkbox" asp-for="RememberMe" />
        </div>
    </div>
    <div class="mb-3 row">
        <div class="col-sm-11 offset-sm-1">
            <button type="submit" class="btn btn-primary">登录</button>
        </div>
    </div>
</form>

并在Login实体类中增加属性:

public class Login
{
	[Required]
	[DisplayName("用户名")]
	public string Email { get; set; } = null!;
	[Required]
	[DisplayName("密码")]
	[DataType(DataType.Password)]
	public string Password { get; set; } = null!;
	public string? ReturnUrl { get; set; }
	[Required]
	[DisplayName("记住密码")]
	public bool RememberMe { get; set; }
}

修改Login登录方法

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(Login login)
{
    if (ModelState.IsValid)
    {
        var appUser = await _userManager.FindByEmailAsync(login.Email);
        if (appUser != null)
        {
            await _signInManager.SignOutAsync();
            var signInResult = await _signInManager.PasswordSignInAsync(appUser, login.Password, 
                login.RememberMe, false);
            if (signInResult.Succeeded)
            {
                return Redirect(login.ReturnUrl ?? "/");
            }
        }
        ModelState.AddModelError(nameof(login.Email),"Login Failed: Invalid Email or password");
    }
    return View(login);
}

image

6. 总结

这节我们主要介绍了在Identity如何认证用户,我们可以为我们WebSite区域做一些安全认证

源代码地址:
https://github.com/bingbing-gui/Asp.Net-Core-Skill/tree/master/AspNetCore.Identity/Identity
补充:ASP.NET Core Identity 系列之三 源代码地址以废弃,上面那是最新地址

标签:Core,ASP,登录,用户,public,之四,Login,login,Identity
From: https://www.cnblogs.com/Ceri/p/17494024.html

相关文章

  • 专业数据科学家的IDE-DataSpell 2023 mac/win版
    DataSpell2023是一款专为数据科学家设计的集成开发环境(IDE),旨在提供强大的数据分析和机器学习工具,帮助用户更高效地处理和分析大规模数据集。→→↓↓载DataSpell2023mac/win版 DataSpell2023提供了丰富的功能和工具,使数据科学家能够完整地执行整个数据科学项目的流程,从......
  • TSN CoreSolutuon开启时间敏感网络测试自动化新篇章
    随着下一代车载网络的快速发展,OEM和TIER1在开发和验证复杂车载网络通信的过程中面临很多新的挑战。为了更好地满足网络测试方面的需求,TSNSystems在原先TSNBox和TSNTools测量工具的基础上,集成了相关的应用程序接口,用来支持各种场景下的自动化测试。这一测试工具链也被正式更名为......
  • net Core基础API 命名空间定义
    ●System.Collections:定义了常用的集合类型。●System.Console:提供API完成基本的控制台操作。●System.Data:提供用于访问数据库的API,相当于原来的ADO.NET。●System.Diagnostics:提供基本的诊断、调试和追踪的API。●System.DirectoryServices:提供基于AD(ActiveDirectory)管理......
  • 【.NET Core】配置复用、替换(GSoft.Extensions.Configuration.Substitution)【转】
    .NET是一个非常强大的框架,它允许开发人员管理来自各种源(如JSON文件、环境变量等)的应用程序设置。但是,有时开发人员需要一种方法来引用和替换其他设置中的配置值,以避免在多个地方维护相同的值,从而使配置文件变得混乱和难以维护。为了解决这个问题,我们可以使用GSoft.Extensions......
  • 如何快速发现 ASP.NET Core 应用程序中的服务生命周期问题?【转】
    在ASP.NETCore中,内置了非常强大的依赖注入容器功能。但是,如果不正确使用,也可能会引起一些问题。问题下面我们通过一段示例代码来说明这个问题。public interface IServiceA{    string Get();}public interface IServiceB{    string Get();}public class S......
  • Armsom推出工规级RK3588J-Core(armsom P1 Core) 8K 智能NVR核心板**
    ArmsomP1Core板载RockchipRK3588J新一代工业级八核64位处理器;采用工业级芯片、精密元器件和BTB连接器,支持宽温温度-40°C~85°C长时间稳定运行;支持ARMPC、边缘计算、云服务器、智能NVR等相关领域;提供10年+超长供货期和完善的技术资料,用户可自主深度化定制。八核工业级处理器RK......
  • 【HMS Core】Health Kit健康数据采样, 原子采样数据问题
    【问题描述】1.体脂数据中的肌肉量和水份量是如何获得的,都有些什么?体脂数据中的体重,体脂是用户自己上传的,然后通过计算公式得到数据吗2.日常活动统计数据包含什么内容,怎么获取这些数据?3.锻炼记录概要数据包含什么内容?是统计数据吗?获取方式呢?4.心脏健康数据测的是心电图相关记录。......
  • ASP.NET Core Identity 系列之三
    在这节中我们将研究ASP.NETCoreIdentity中用户名、邮件、密码策略,解释一下Identity默认提供的策略以及如何实现自定义策略,最后我们针对用户名、邮件、密码实现客户自定义策略1.ASP.NETCoreIdentity密码策略ASP.NETCoreIdentity默认的密码策略要求密码满足如下条件:密码......
  • asp.net使用sapnco3.x64,未能加载文件或程序集“XXX”或它的某一个依赖项。试图加载格
    报错原因:引用了sapnco3.x64的dll之后将web应用程序改为了64位,VS启动报错,未能加载文件或程序集“XXX”或它的某一个依赖项。试图加载格式不正确的程序。造成这种故障的原因是,大部分asp.net编译器和容器并没有默认设置为64位,而是以32位兼容模式运行。如果将程序库更换为32位,则运行......
  • 终端运行roscore时,报错:Unable to contact my own server at...
    问题现象:问题原因:以上问题是由于ROS环境变量ROS_MASTER_URI设置错误导致的,重新设置该变量即可。解决方法:打开~/.bashrc文件,添加或修改环境变量ROS_HOSTNAME和ROS_MASTER,即改为:exportROS_HOSTNAME=localhostexportROS_MASTER_URI=http://localhost:11311修改并保存~/.......