Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >用最简单的方式在ASP.NET Core应用中实现认证、登录和注销

用最简单的方式在ASP.NET Core应用中实现认证、登录和注销

作者头像
蒋金楠
发布于 2020-03-26 07:21:05
发布于 2020-03-26 07:21:05
3.6K00
代码可运行
举报
文章被收录于专栏:大内老A大内老A
运行总次数:0
代码可运行
在安全领域,认证和授权是两个重要的主题。认证是安全体系的第一道屏障,是守护整个应用或者服务的第一道大门。当访问者请求进入的时候,认证体系通过验证对方的提供凭证确定其真实身份。认证体系只有在证实了访问者的真实身份的情况下才会允许其进入。ASP.NET Core提供了多种认证方式,它们的实现都基于相同的认证模型。本篇文章提供了一个极简的实例让读者体验如何在ASP.NET Core应用中实现认证、登录和注销。

本篇文章节选自《ASP.NET Core 3框架揭秘》(下册),针对本书的限时5折优惠截至到今天24时,有兴趣的朋友可以通过加入读者群进行购买。入群方式:扫描右方二维码添加“博文小丸子(broadview002)”,并将本书书号“38462”作为验证信息。源代码从这里下载。

一、认证票据

认证是一个旨在确定请求访问者真实身份的过程,与认证相关的还有其他两个基本操作——登录与注销。要真正理解认证、登录与注销这3个核心操作的本质,就需要对ASP.NET Core采用的基于“票据”的认证机制有基本的了解。ASP.NET Core应用的认证实现在一个名为AuthenticationMiddleware的中间件中,该中间件在处理分发给它的请求时会按照指定的认证方案(Authentication Scheme)从请求中提取能够验证用户真实身份的数据,我们一般将该数据称为安全令牌(Security Token)。ASP.NET Core应用下的安全令牌被称为认证票据(Authentication Ticket),所以ASP.NET Core应用采用基于票据的认证方式。

AuthenticationMiddleware中间件实现的整个认证流程涉及下图所示的3种针对认证票据的操作,即认证票据的颁发、检验和撤销。我们将这3个操作所涉及的3种角色称为票据颁发者(Ticket Issuer)、验证者(Authenticator)和撤销者(Ticket Revoker),在大部分场景下这3种角色由同一个主体来扮演。

颁发认证票据的过程就是登录(Sign In)操作。一般来说,用户试图通过登录应用以获取认证票据的时候需要提供可用来证明自身身份的用户凭证(User Credential),最常见的用户凭证类型是“用户名 + 密码”。认证方在确定对方真实身份之后,会颁发一个认证票据,该票据携带着与该用户相关的身份、权限及其他相关的信息。

一旦拥有了由认证方颁发的认证票据,我们就可以按照双方协商的方式(如通过Cookie或者报头)在请求中携带该认证票据,并以此票据声明的身份执行目标操作或者访问目标资源。认证票据一般都具有时效性,一旦过期将变得无效。我们有的时候甚至希望在过期之前就让认证票据无效,以免别人使用它冒用自己的身份与应用进行交互,这就是注销(Sign Out)操作。

ASP.NET Core应用的认证系统旨在构建一个标准的模型来完成针对请求的认证以及与之相关的登录和注销操作。接下来我们就通过一个简单的实例来演示如何在一个ASP.NET Core应用中实现认证、登录和注销的功能。

二、基于Cookie的认证

我们会采用ASP.NET Core提供的基于Cookie的认证方案。顾名思义,该认证方案采用Cookie来携带认证票据。为了使读者对基于认证的编程模式有深刻的理解,我们演示的这个应用将从一个空白的ASP.NET Core应用开始搭建。

我们即将创建的这个ASP.NET Core应用主要处理3种类型的请求。应用的主页需要登录之后才能访问,所以针对主页的匿名请求会被重定向到登录页面。在登录页面输入正确的用户名和密码之后,应用会自动重定向到应用主页,该页面会显示当前认证用户名并提供注销的链接。我们按照如下所示的方式利用路由来处理这3种类型的请求,其中登录和注销采用的是默认路径“Account/Login”与“Account/Logout”。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Program
{
    public static void Main()
    {
        Host.CreateDefaultBuilder()
            .ConfigureWebHostDefaults(builder => builder
                .ConfigureServices(svcs => svcs.AddRouting()) 
                .Configure(app => app
                    .UseRouting()
                    .UseEndpoints(endpoints =>{
                        endpoints.Map(pattern: "/", RenderHomePageAsync);
                        endpoints.Map("Account/Login", SignInAsync);
                        endpoints.Map("Account/Logout", SignOutAsync);
                        })))                   
            .Build()
            .Run();
    }

    public static async Task RenderHomePageAsync(HttpContext context)
    {
        throw new NotImplementedException();
    }

    public static async Task SignInAsync(HttpContext context)
    {
        throw new NotImplementedException();
    }

    public static async Task SignOutAsync(HttpContext context)
    {
        throw new NotImplementedException();
    }
}

三、应用主页

如下面的代码片段所示,我们调用IApplicationBuilder接口的UseAuthentication扩展方法就是为了注册用来实现认证的AuthenticationMiddleware中间件。该中间件的依赖服务是通过调用IServiceCollection接口的AddAuthentication扩展方法注册的。在注册这些基础服务时,我们还设置了默认采用的认证方案,静态类型CookieAuthenticationDefaults的AuthenticationScheme属性返回的就是Cookie认证方案的默认方案名称。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Program
{
    public static void Main()
    {
        Host.CreateDefaultBuilder()
            .ConfigureWebHostDefaults(builder => builder
                .ConfigureServices(svcs => svcs
                    .AddRouting()
                    .AddAuthentication(options => options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme)
                        .AddCookie())
                .Configure(app => app
                    .UseAuthentication()
                    .UseRouting()
                    .UseEndpoints(endpoints =>{
                        endpoints.Map(pattern: "/", RenderHomePageAsync);
                        endpoints.Map("Account/Login", SignInAsync);
                        endpoints.Map("Account/Logout", SignOutAsync);
                        })))                   
            .Build()
            .Run();
    }
}

ASP.NET Core提供了一个极具扩展性的认证模型,我们可以利用它支持多种认证方案,针对认证方案的注册是通过AddAuthentication方法返回的一个AuthenticationBuilder对象来实现的。在上面提供的代码片段中,我们调用AuthenticationBuilder对象的AddCookie扩展方法完成了针对Cookie认证方案的注册。

演示实例的主页是通过如下所示的RenderHomePageAsync方法来呈现的。由于我们要求浏览主页必须是经过认证的用户,所以该方法会利用HttpContext上下文的User属性返回的ClaimsPrincipal对象判断当前请求是否经过认证。对于经过认证的请求,我们会响应一个简单的HTML文档,并在其中显示用户名和一个注销链接。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Program
{
    ...
    public static async Task RenderHomePageAsync(HttpContext context)
    {
        if (context?.User?.Identity?.IsAuthenticated == true)
        {
            await context.Response.WriteAsync(
                @"<html>
                    <head><title>Index</title></head>
                    <body>" +
                        $"<h3>Welcome {context.User.Identity.Name}</h3>" +
                        @"<a href='Account/Logout'>Sign Out</a>
                    </body>
                </html>");
        }
        else
        {
            await context.ChallengeAsync();
        }
    }
}

对于匿名请求,我们希望应用能够自动重定向到登录路径。从如上所示的代码片段可以看出,我们仅仅调用当前HttpContext上下文的ChallengeAsync扩展方法就完成了针对登录路径的重定向。前面提及,注册的登录和注销路径是基于Cookie的认证方案采用的默认路径,所以调用ChallengeAsync方法时根本不需要指定重定向路径。下图所示就是作为应用的主页在浏览器上呈现的效果。

四、登录

登录与注销分别实现在SignInAsync方法和SignOutAsync方法中,我们采用的是针对“用户名 + 密码”的登录方式,所以可以利用静态字段_accounts来存储应用注册的账号。在静态构造函数中,我们添加密码均为“password”的3个账号(Foo、Bar和Baz)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Program
{
    private static Dictionary<string, string> _accounts;
    static Program()
    {
        _accounts = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
        _accounts.Add("Foo", "password");
        _accounts.Add("Bar", "password");
        _accounts.Add("Baz", "password");
    }
}

如下所示的代码片段是用于处理登录请求的SignInAsync方法的定义,而RenderLoginPageAsync方法用来呈现登录页面。如下面的代码片段所示,对于GET请求,SignInAsync方法会直接调用RenderLoginPageAsync方法来呈现登录界面。对于POST请求,我们会从提交的表单中提取用户名和密码,并对其实施验证。如果提供的用户名与密码一致,我们会根据用户名创建一个代表身份的GenericIdentity对象,并利用它创建一个代表登录用户的ClaimsPrincipal对象,RenderHomePageAsync方法正是利用该对象来检验当前用户是否经过认证的。有了ClaimsPrincipal对象,我们只需要将它作为参数调用HttpContext上下文的SignInAsync扩展方法即可完成登录,该方法最终会自动重定向到初始方法的路径,也就是我们的主页。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Program
{
    public static async Task SignInAsync(HttpContext context)
    {
        if (string.Compare(context.Request.Method, "GET") == 0)
        {             
            await RenderLoginPageAsync(context, null, null, null);
        }
        else
        {
            var userName = context.Request.Form["username"];
            var password = context.Request.Form["password"];
            if (_accounts.TryGetValue(userName, out var pwd) && pwd == password)
            {
                var identity = new GenericIdentity(userName, "Passord");
                var principal = new ClaimsPrincipal(identity);
                await context.SignInAsync(principal);
            }
            else
            {
                await RenderLoginPageAsync(context, userName, password, "Invalid user name or password!");
            }
        }
    }

    private static Task RenderLoginPageAsync(HttpContext context, string userName,  string password, string errorMessage)
    {
        context.Response.ContentType = "text/html";
        return context.Response.WriteAsync(
            @"<html>
                <head><title>Login</title></head>
                <body>
                    <form method='post'>" +
                            $"<input type='text' name='username' placeholder='User name' value ='{userName}'/>" +
                            $"<input type='password' name='password' placeholder='Password'  value ='{password}'/> " +
                            @"<input type='submit' value='Sign In' /></form>" +
                    $"<p style='color:red'>{errorMessage}</p>" +
                @"</body>
            </html>");
    }
}

如果用户提供的用户名与密码不匹配,我们还是会调用RenderLoginPageAsync方法来呈现登录页面,该页面会以下图所示的形式保留用户的输入并显示错误消息。图19-3还反映了一个细节,调用HttpContext上下文的ChallengeAsync方法会将当前路径(主页路径“/”,经过编码后为“%2F”)存储在一个名为ReturnUrl的查询字符串中,SignInAsync方法正是利用它实现对初始路径的重定向的。

五、注销

既然登录可以通过调用当前HttpContext上下文的SignInAsync扩展方法来完成,那么注销操作对应的自然就是SignOutAsync扩展方法。如下面的代码片段所示,我们定义在Program中的SignOutAsync扩展方法正是调用这个方法来注销当前登录状态的。我们在完成注销之后将应用重定向到主页。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Program
{    
    ...
    public static async Task SignOutAsync(HttpContext context)
    {
        await context.SignOutAsync();
        context.Response.Redirect("/");   
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-03-25 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
ASP.NET Core 6框架揭秘实例演示[39]:使用最简洁的代码实现登录、认证和注销
认证是一个确定请求访问者真实身份的过程,与认证相关的还有其他两个基本操作——登录和注销。ASP.NET Core利用AuthenticationMiddleware中间件完成针对请求的认证,并提供了用于登录、注销以及“质询”的API,本篇文章利用它们使用最简单的代码实现这些功能。(本文提供的示例演示已经同步到《ASP.NET Core 6框架揭秘-实例演示版》)
蒋金楠
2023/07/10
3350
ASP.NET Core 6框架揭秘实例演示[39]:使用最简洁的代码实现登录、认证和注销
ASP.NET Core Authentication系列(二)实现认证、登录和注销
在上一篇文章介绍ASP.NET Core Authentication的三个重要概念,分别是Claim, ClaimsIdentity, ClaimsPrincipal,以及claims-base authentication是怎么工作的。
梁规晓
2020/11/05
3.5K0
ASP.NET Core Authentication系列(二)实现认证、登录和注销
ASP.NET Core 6框架揭秘实例演示[40]:基于角色的授权
ASP.NET应用并没有对如何定义授权策略做硬性规定,所以我们完全根据用户具有的任意特性(如性别、年龄、学历、所在地区、宗教信仰、政治面貌等)来判断其是否具有获取目标资源或者执行目标操作的权限,但是针对角色的授权策略依然是最常用的。角色(或者用户组)实际上就是对一组权限集的描述,将一个用户添加到某个角色之中就是为了将对应的权限赋予该用户。在《使用最简洁的代码实现登录、认证和注销》中,我们提供了一个用来演示登录、认证和注销的程序,现在我们在此基础上添加基于“角色授权的部分”。(本文提供的示例演示已经同步到《ASP.NET Core 6框架揭秘-实例演示版》)
蒋金楠
2023/07/10
3270
ASP.NET Core 6框架揭秘实例演示[40]:基于角色的授权
在 ASP.NET Core 应用中使用 Cookie 进行身份认证
身份认证是网站最基本的功能,最近因为业务部门的一个需求,需要对一个已经存在很久的小工具网站进行改造,因为在逐步的将一些离散的系统迁移至 .NET Core,所以趁这个机会将这个老的 .NET Framework 4.0 的项目进行升级
程序员宇说
2021/02/04
1.4K0
在 ASP.NET Core 应用中使用 Cookie 进行身份认证
理解ASP.NET Core - Cookie 的身份认证
链接:cnblogs.com/xiaoxiaotank/p/15811749.html
郑子铭
2022/03/22
1K0
理解ASP.NET Core - Cookie 的身份认证
.NET core3.1使用cookie进行身份认证
一个系统,用户身份认证少不了,ASP.NET Core提供完整的解决方案Identity,用户创建和维护登录名;也提供能cookie和JwtBearer认证方案,当然你可以使用第三方认证Oauth、openId。项目没有采用前后端分离,是一个标准的mvc项目,所以本文采用系统提供的cookie认证 记录一下简单认证流程,(1)使用用户账号密码进行登录,验证合法登录(2)确认合法身份之后,会颁发一个认证票据(加密)会携带与该用户相关的身份、权限以及其他信息。(3)退出。
李明成
2020/08/28
1.3K0
ASP.NET Core 中的那些认证中间件及一些重要知识点
在读这篇文章之间,建议先看一下我的 ASP.NET Core 之 Identity 入门系列(一,二,三)奠定一下基础。
郑子铭
2022/03/22
1.9K0
ASP.NET Core 中的那些认证中间件及一些重要知识点
ASP.NET Core Authentication and Authorization
最近把一个Asp .net core 2.0的项目迁移到Asp .net core 3.1,项目启动的时候直接报错:
MJ.Zhou
2020/04/08
1.2K0
ASP.NET Core Authentication and Authorization
ASP.NET Core Cookie 认证
Cookie 认证是ASP.NET Core用来实现客户自定义认证逻辑,没有使用ASP.NET Core Identity
郑子铭
2023/12/13
2530
ASP.NET Core Cookie 认证
使用cookie来做身份认证
这里先讲一下Authentication和Authorization两个词的区别。
_淡定_
2018/08/28
3.6K0
ASP.NET Core 中基于 Cookie 的身份鉴权实现
在 ASP.NET Core 应用中,基于 Cookie 的身份鉴权是一种常见的身份验证方式,特别适用于传统的 Web 应用程序。Cookie 能够在用户的浏览器中存储身份验证数据,从而在用户访问应用的不同页面时保持登录状态。
郑子铭
2025/03/11
790
ASP.NET Core 中基于 Cookie 的身份鉴权实现
asp.net core 认证及简单集群
众所周知,在Asp.net WebAPI中,认证是通过AuthenticationFilter过滤器实现的,我们通常的做法是自定义AuthenticationFilter,实现认证逻辑,认证通过,继续管道处理,认证失败,直接返回认证失败结果,类似如下:
guokun
2020/09/03
1.2K0
asp.net core 认证及简单集群
ASP.NET Core快速入门(第6章:ASP.NET Core MVC)--学习笔记
课程链接:http://video.jessetalk.cn/course/explore
郑子铭
2021/01/13
2.3K0
ASP.NET Core快速入门(第6章:ASP.NET Core MVC)--学习笔记
.Net Core系列教程(四)—— 基础身份认证
在ASP.NET 4.5及之前的版本,可以使用FormsAuthenticationTicket来做基础身份认证,现在到了.Net Core中,发现原来的FormsAuthenticationTicket不能用了,其实在.Net Core中,依然可以使用基础身份认证,下面是使用方法。因为这是在具体项目中使用的,会多出一些其他的代码,请自行忽略。
徐大嘴
2019/03/21
2.5K0
ASP.NET Core错误处理中间件[1]: 呈现错误信息
NuGet包“Microsoft.AspNetCore.Diagnostics”中提供了几个与异常处理相关的中间件。当ASP.NET Core应用在处理请求过程中出现错误时,我们可以利用它们将原生的或者定制的错误信息作为响应内容发送给客户端。在着重介绍这些中间件之前,下面先演示几个简单的实例,从而使读者大致了解这些中间件的作用。[更多关于ASP.NET Core的文章请点这里]
蒋金楠
2021/01/18
1.7K0
【asp.net core 系列】13 Identity 身份验证入门
通过前两篇我们实现了如何在Service层如何访问数据,以及如何运用简单的加密算法对数据加密。这一篇我们将探索如何实现asp.net core的身份验证。
程序员小高
2020/06/24
1K0
asp.net core 3.1多种身份验证方案,cookie和jwt混合认证授权
开发了一个公司内部系统,使用asp.net core 3.1。在开发用户认证授权使用的是简单的cookie认证方式,然后开发好了要写几个接口给其它系统调用数据。并且只是几个简单的接口不准备再重新部署一个站点,所以就直接在MVC的项目里面加了一个API区域用来写接口。这时候因为是接口所以就不能用cookie方式进行认证,得加一个jwt认证,采用多种身份验证方案来进行认证授权。
SpringSun
2020/08/11
5K0
asp.net core 3.1多种身份验证方案,cookie和jwt混合认证授权
IdentityServer Topics(4)- 登录
为了使IdentityServer代表用户发布令牌,该用户必须登录到IdentityServer。 Cookie认证 使用来自ASP.NET Core的cookie身份验证处理程序管理的cookie跟踪身份验证。 IdentityServer注册两个cookie处理程序(一个用于身份验证会话,另一个用于临时的外部cookie)。 这些在默认情况下使用,如果您想手动引用它们,您可以从IdentityServerConstants类(DefaultCookieAuthenticationScheme和Exter
晓晨
2018/06/22
1.3K0
IdentityServer Topics(5)- 使用第三方登录
ASP.NET Core有一个灵活的方式来处理外部认证。 这包括几个步骤。 如果您使用的是ASP.NET Identity,则许多底层技术细节对您而言都是隐藏的。 建议您还阅读Microsoft文档并查看ASP.NET Identity快速入门源码。 添加外部认证处理程序 与外部提供者交互所需的协议实现被封装在一个认证处理程序中。 一些提供者使用专有协议(例如Facebook等社交提供者),一些使用标准协议, OpenID Connect,WS-Federation或SAML2p。 请参阅此快速入门以了解添
晓晨
2018/06/22
3K3
ASP.NET Core应用的7种依赖注入方式
构成HostBuilderContext上下文的两个核心对象(表示配置的IConfiguration对象和表示承载环境的IHostEnvironment对象)可以直接注入Startup构造函数中进行消费。由于ASP.NET Core应用中的承载环境通过IWebHostEnvironment接口表示,IWebHostEnvironment接口派生于IHostEnvironment接口,所以也可以通过注入IWebHostEnvironment对象的方式得到当前承载环境相关的信息。
蒋金楠
2020/03/26
1.8K0
推荐阅读
相关推荐
ASP.NET Core 6框架揭秘实例演示[39]:使用最简洁的代码实现登录、认证和注销
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验