前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ASP.NET Core Cookie 认证

ASP.NET Core Cookie 认证

作者头像
郑子铭
发布2023-12-13 11:21:06
1860
发布2023-12-13 11:21:06
举报
文章被收录于专栏:DotNet NB && CloudNative

Cookie 认证是ASP.NET Core用来实现客户自定义认证逻辑,没有使用ASP.NET Core Identity

1 ASP.NET Core Cookie 认证例子

在.NET Core我们通常使用三步来配置cookie认证,第一步是使用AddAuthentication和AddCookie添加Authentication服务,第二步指定app必须使用Authentication&Authorization中间件,最后在需要 cookie 授权的控制器和操作上应用 [Authorize] 属性

2 配置

首先我们需要配置Cookie认证,如下代码展示如何配置Cookie认证

代码语言:javascript
复制
using Microsoft.AspNetCore.Authentication.Cookies;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie(options =>
            {
                options.LoginPath = "/Home/Login";
                options.Cookie.Name = ".AspNetCore.Cookies";
                options.ExpireTimeSpan = TimeSpan.FromMinutes(10);
                options.SlidingExpiration = true;
            });
var app = builder.Build();

在上面代码我们在AddAuthentication()方法中使用CookieAuthenticationDefaults.AuthenticationScheme参数设置应用程序默认认证方法

这意味着登录成功后将为通过身份验证的用户创建一个cookie,这个cookie名字为.ASPNetCore.Cookies

我们设置HomeController的Login方法中登录URL

代码语言:javascript
复制
options.LoginPath = "/Home/Login";

这意味着如果一个未授权的用户尝试访问应用程序安全的URL时将会被自动跳转到/Home/Login, 在登录页面输入用户名和密码进行授权

第二件要做的事情是告诉应用程序用认证和授权,通过添加如下代码实现:

代码语言:javascript
复制
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();

调用UseAuthentication& UseAuthorization()方法

3 认证和授权

现在我们在ASP.NET Core 应用程序中使用Cookie认证,在这个应用程序创建2个Controllers如下图所示:

3.1 HomeController.cs

在Home控制器我们有Login和Logout特性,使用Login特性,用户能够登录应用程序,使用Logout特性用户能够退出应用程序

3.2 SecuredController.cs

Secured控制器能只允许登录的用户进行访问,这个控制器有[Authorize]特性

创建一个Controller叫SecuredController.cs,添加[Authorize]特性,所有控制器内部的方法都继承了authorize特性,这意味着所有的action方法只允许授权的用户访问

代码语言:javascript
复制
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace AspNetCore.Cookie.Controllers
{
    [Authorize]
    public class SecuredController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
    }
}

接下来,使用下面代码创建Index试图在Views->Secured文件夹

代码语言:javascript
复制
<form method="post" asp-controller="Home" asp-action="Logout">
    <button class="btn btn-lg btn-primary btn-block">Logout</button>
</form>

这个视图表单有一个button按钮,当button点击时,Home控制器Logout方法被调用,当前用户会退出系统

4 Cookie登录授权

下面代码在Home控制器中添加一个Login方法:

代码语言:javascript
复制
using AspNetCore.Cookie.Models;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using System.Security.Claims;
namespace AspNetCore.Cookie.Controllers
{
    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;

        public HomeController(ILogger<HomeController> logger)
        {
            _logger = logger;
        }
        public IActionResult Index()
        {
            return View();
        }
        public IActionResult Login()
        {
            return View();
        }
        public async Task<IActionResult> Login(string username, string password, string ReturnUrl)
        {
            if ((username == "Admin") && (password == "Admin"))
            {
                var claims = new List<Claim>
                {
                    new Claim(ClaimTypes.Name, username)
                };
                var claimsIdentity = new ClaimsIdentity(claims, "Login");
                await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity));
                return Redirect(ReturnUrl == null ? "/Secured" : ReturnUrl);
            }
            else
                return View();
        }
        public IActionResult Privacy()
        {
            return View();
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}

Login方法使用了string username, string password, string ReturnUrl在参数中,首先进行检查以确定用户的用户名和密码是否都是管理员用户名和密码,在真实环境中,我们将从数据库中获取用户名和密码与用户输入的用户名和密码进行匹配,在这里为了方便我们使用静态的用户名和密码

代码语言:javascript
复制
if ((username == "Admin") && (password == "Admin"))
{
//…
}

接下来,对用户进行授权,使用用户信息创建一个Cookie,构造一个ClaimsPrincipal序列化用户信息并储到Cookie

代码语言:javascript
复制
var claims = new List<Claim>
{
    new Claim(ClaimTypes.Name, username)
};
var claimsIdentity = new ClaimsIdentity(claims, "Login");

调用SignInAsync()方法对用户进行登录,它使用2个参数:

1.CookieAuthenticationDefaults.AuthenticationScheme

2.ClaimsPrincipal

SignInAsync()方法如下:

代码语言:javascript
复制
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity));

用户登录之后,用户跳转return URL

代码语言:javascript
复制
return Redirect(ReturnUrl == null ? "/Secured" : ReturnUrl);

现在,在Home文件夹下创建一个Login视图文件代码如下:

代码语言:javascript
复制
<form class="form-horizontal" action="login" role="form" method="post">
    <div class="mb-3 row">
        <label class="col-sm-1 control-label">用户名</label>
        <div class="col-sm-11">
            <input name="username" class="form-control" />
        </div>
    </div>
    <div class="mb-3 row">
        <label class="col-sm-1 control-label">密码</label>
        <div class="col-sm-11">
            <input name="password" type="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>

测试

运行应用程序尝试访问Secured控制器的Index方法,由于用户没有登录因此将会跳转到Login页面,如下图所示:

现在输入用户名和密码点击登录,登录之后将会跳转到Secured页面,一旦用户经过身份验证,.ASPNetCore.Cookies 的 Cookie 将被创建并存储在浏览器中,我们可以在浏览器的“开发者工具”的“应用程序”区域中看到这个 Cookie,如下图所示

Cookie认证超时

我们可以使用ConfigureApplicationCookie方法设置Cookie的期限,下面代码以滑动方式启用cookie的超时时间:

代码语言:javascript
复制
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie(options =>
            {
                options.LoginPath = "/Home/Login";
                options.Cookie.Name = ".AspNetCore.Cookies";
                options.ExpireTimeSpan = TimeSpan.FromMinutes(10);
                options.SlidingExpiration = true;
            });

Cookie认证返回URL

应用程序会记住用户在身份验证之前在浏览器中打开的安全 URL,因此应用程序将用户导向到登录页面并且添加用户请求的地址,用户尝试打开的url被添加到浏览器查询字符串中,一旦用户成功授权,应用程序从查询字符串中读取return url,并跳转到这个url

当我们在浏览器中打开secured地址,页面会跳转到https://localhost:7262/Home/Login?ReturnUrl=%2FSecured,注意查询字符串值包含Return url, 当我们登录成功之后,应用程序将跳转到这个url

4 Logout特性

接下里,添加Logout方法在Home控制器中,包含下面代码:

代码语言:javascript
复制
[HttpPost]
public async Task<IActionResult> Logout()
{
    await HttpContext.SignOutAsync();
    return RedirectToAction("Index", "Home");
}

调用SignOutAsync()方法退出当前用户,这个方法从浏览器中移除认证Cookie

源代码地址:

https://github.com/bingbing-gui/Asp.Net-Core-Skill/tree/master/Fundamentals/AspNetCore.Security/AspNetCore.Cookie

参考文献

https://www.yogihosting.com/aspnet-core-cookie-authentication/

https://learn.microsoft.com/en-us/aspnet/core/security/authentication/cookie?view=aspnetcore-7.0

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-12-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DotNet NB 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
多因子身份认证
多因子身份认证(Multi-factor Authentication Service,MFAS)的目的是建立一个多层次的防御体系,通过结合两种或三种认证因子(基于记忆的/基于持有物的/基于生物特征的认证因子)验证访问者的身份,使系统或资源更加安全。攻击者即使破解单一因子(如口令、人脸),应用的安全依然可以得到保障。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档