asp.netcore实现随处可见的基本身份认证(代码片段)

lonelyxmas lonelyxmas     2022-12-05     502

关键词:

原文:ASP.NET Core实现 随处可见的基本身份认证

 

概览

       在HTTP中,基本认证(Basic access authentication,简称BA认证)是一种用来允许网页浏览器或其他客户端程序在请求资源时提供用户名和口令形式的身份凭证的一种登录验证方式,不要求cookie,session identifier、login page等标记或载体。  

优点:基本上所有流行的网页浏览器都支持BA认证。

缺点:明文传输密钥和口令(容易被拦截); 没有对服务器返回的信息提供保护。

 https://en.wikipedia.org/wiki/Basic_access_authentication

特征

        基本身份认证原理不保证传输凭证的安全性,他们仅仅只是被based64编码,并没有encrypted或者hashed。

一般部署在可信任网络,在公开网络中部署BA认证通常要与https结合使用。

因为基本身份认证字段在HTTP Header 中发送,所以web browser需要在一个合理的时间内缓存凭据,缓存策略因浏览器不同而异,IE默认缓存15 分钟。 HTTP不会为客户端提供一个logout方法,但是有很多方法在浏览器中可以清除缓存凭据。

<script>document.execCommand(ClearAuthenticationCache);</script>

 IIS-WebSite-身份认证:

技术图片

 

BA认证的标准协议

BA认证协议的实施主要依靠约定的请求头/响应头, 典型的浏览器和服务器的BA认证流程,包含以下步骤:

1.浏览器请求一个需要身份认证的页面,但是没有提供用户名和口令。这通常是用户在地址栏输入一个URL,或是打开了一个指向该页面的链接。

2.服务端响应一个401应答码,并提供一个认证域。

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="180.76.176.244"

3.接到应答后,浏览器显示该认证域并提示输入用户名和口令。此时用户可以选择确定或取消。

4.用户输入了用户名和口令后,浏览器会在原请求方式上增加认证消息头Authorization:base64encode(username+":"+password),然后重新发送再次尝试。

// 下面的例子显示:认证双方约定在编码字符串前加上了此次认证的方式和一个空格: Basic:

Authorization: Basic RmlzYWRzYWQ6YXNkYWRz

5.服务器接受该认证凭据并返回页面;如果用户凭据非法或无效,服务器可能再次返回401应答码,客户端可以再次提示用户输入口令。

 技术图片

 注意:
① 客户端用户名,口令之间用冒号分隔
② 服务端返回认证域,可能会指定凭据字符串的编码方式:

WWW-Authenticate: Basic realm="User Visible Realm", charset="UTF-8"

       此时客户端在准备凭据字符串的时候,要使用指定的charset编码凭据

③ 客户端未认证时,服务端需要给客户端必要的认证域提示,效果如下:

  技术图片

BA认证编程实践

     项目中利用StaticFileMiddleware+DirectoryBrowserMiddleware做了一个网页文件服务器, 现对该文件服务器设置BA认证。

ASP.NET Core服务端实现BA认证:

  1. 实现基本身份认证Handler, 包含认证方式、认证挑战的提示

  2. asp.netcore 添加认证中间件

  3. 注册认证中间件

public class BasicAuthenticationHandler : AuthenticationHandler<BasicAuthenticationOption>
   
       private BasicAuthenticationOption authOptions;
       public BasicAuthenticationHandler(
           IOptionsMonitor<BasicAuthenticationOption> options,
           ILoggerFactory logger,
           UrlEncoder encoder,
           ISystemClock clock)
           : base(options, logger, encoder, clock)
       
           authOptions = options.CurrentValue;
       

       /// <summary>
       /// BA认证过程
       /// </summary>
       /// <returns></returns>
       protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
       
           if (!Request.Headers.ContainsKey("Authorization"))
               return AuthenticateResult.Fail("Missing Authorization Header");
           string username, password;
           try
           
               var authHeader = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]);
               var credentialBytes = Convert.FromBase64String(authHeader.Parameter);
               var credentials = Encoding.UTF8.GetString(credentialBytes).Split(:);
                username = credentials[0];
                password = credentials[1];
                var isValidUser= IsAuthorized(username,password);
               if(isValidUser== false)
               
                   return AuthenticateResult.Fail("Invalid username or password");
               
           
           catch
           
               return AuthenticateResult.Fail("Invalid Authorization Header");
           

           var claims = new[] 
               new Claim(ClaimTypes.NameIdentifier,username),
               new Claim(ClaimTypes.Name,username),
           ;
           var identity = new ClaimsIdentity(claims, Scheme.Name);
           var principal = new ClaimsPrincipal(identity);
           var ticket = new AuthenticationTicket(principal, Scheme.Name);
           return await Task.FromResult(AuthenticateResult.Success(ticket));
       

       /// <summary>
       /// 重写该方法以体现身份验证挑战(401)时发生时提示
       /// </summary>
       /// <param name="properties"></param>
       /// <returns></returns>
       protected override async Task HandleChallengeAsync(AuthenticationProperties properties)
       
           Response.Headers["WWW-Authenticate"] = $"Basic realm=\\"Options.Realm\\",charset=\\"utf-8\\"";
           await base.HandleChallengeAsync(properties);
       

       /// <summary>  进行BA认证,此处不关注该方法
       /// override the method to influence what happens when an forbidden response (403) 
       /// </summary>
       /// <param name="properties"></param>
       /// <returns></returns>
       protected override async Task HandleForbiddenAsync(AuthenticationProperties properties)
       
          await base.HandleForbiddenAsync(properties); 
       
       //  BA认证:账户、密码匹配逻辑
       private bool IsAuthorized(string username, string password)
       
           return username.Equals(authOptions.UserName, StringComparison.InvariantCultureIgnoreCase)
                  && password.Equals(authOptions.UserPwd);
       
   

 

// 添加BA认证计划
services.AddAuthentication(BasicAuthentication.DefaultScheme) .AddScheme
<BasicAuthenticationOption, BasicAuthenticationHandler>(BasicAuthentication.DefaultScheme,null);

 

// 这里我使用UseWhen方式注册认证中间件: 对该网站部分资源 开启基本身份认证
app.UseWhen( predicate:x
=> x.Request.Path.StartsWithSegments(new PathString(_protectedResourceOption.Path)), configuration:appBuilder => appBuilder.UseAuthentication() );

 

客户端:

  1.  添加认证请求Handler
  2.  以上述Handler 配置命名HtttpClient
    /// <summary>
    /// BA认证请求Handler
/// </summary> public class BasicAuthenticationClientHandler : HttpClientHandler public static string BAHeaderNames = "authorization"; private RemoteBasicAuth _remoteAccount; public BasicAuthenticationClientHandler(RemoteBasicAuth remoteAccount) _remoteAccount = remoteAccount; AllowAutoRedirect = false; UseCookies = true; protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) var authorization = $"_remoteAccount.UserName:_remoteAccount.Password"; var authorizationBased64 = "Basic " + Convert.ToBase64String(new ASCIIEncoding().GetBytes(authorization)); request.Headers.Remove(BAHeaderNames); request.Headers.Add(BAHeaderNames, authorizationBased64); return base.SendAsync(request, cancellationToken);

 

// 配置命名HttpClient
services.AddHttpClient("eqid-ba-request", x => x.BaseAddress = new Uri(_proxyOption.Scheme +"://"+ _proxyOption.Host+":"+_proxyOption.Port ) ) .ConfigurePrimaryHttpMessageHandler(y => new BasicAuthenticationClientHandler(_remoteAccount) ) .SetHandlerLifetime(TimeSpan.FromMinutes(2)) .AddPolicyHandler(GetRetryPolicy());

asp.netcore认证原理和实现

...效,那么API端应该拒绝提供服务。在命名空间Microsoft.AspNetCore.Authentication下,定义关于验证的核心接口。对应的程序集是Microsoft.AspNetCore.Authentication.Abstractions.dll。在ASP.NET下,验证中包含3个基本操作:验证操作负责基于当前请求... 查看详情

asp.netcore搭载envoy实现微服务身份认证(jwt)

本文内容搭建Keycloak配置Envoy编写API服务编排本文小结在构建以gRPC为核心的微服务架构的过程中,得益于Envoy对gRPC的“一等公民”支持,我们可以在过滤器中对gRPC服务进行转码,进而可以像调用WebAPI一样去调用一个gRPC服务。通... 查看详情

asp.netcore搭载envoy实现微服务身份认证(jwt)

本文内容搭建Keycloak配置Envoy编写API服务编排本文小结在构建以gRPC为核心的微服务架构的过程中,得益于Envoy对gRPC的“一等公民”支持,我们可以在过滤器中对gRPC服务进行转码,进而可以像调用WebAPI一样去调用一个gRPC服务。通... 查看详情

asp.netcore实现带认证功能的web代理服务器(代码片段)

原文:ASP.NETCore实现带认证功能的Web代理服务器引言  最近在公司开发了一个项目,项目部署架构图如下:思路  如图中文本所述,公司大数据集群不允许直接访问外网,需要一个网关服务器代理请求,本处服务器A就是边缘... 查看详情

ASP.NET Core 3.1 中的证书身份验证实现

】ASP.NETCore3.1中的证书身份验证实现【英文标题】:CertificateAuthenticationImplementationinASP.NETCore3.1【发布时间】:2020-03-0117:07:31【问题描述】:我正在ASP.NETCore证书身份验证中构建一个小功能,如officialdocs中给出的。注意:我不是在... 查看详情

如何在asp.netcore中实现一个基础的身份认证

...basicauthorizationinASP.NETCore如何在ASP.NETCore中实现一个基础的身份认证ASP.NET终于可以跨平台了,但是不是我们常用的ASP.NET,而是叫一个ASP.NETCore的新平台,他可以跨Windows,Linux,OSX等平台来部署你的web应用程序,你可以理解为,这个框... 查看详情

未调用 ASP.NET Core 3 中依赖注入服务的具体实现

】未调用ASP.NETCore3中依赖注入服务的具体实现【英文标题】:ConcreteimplementationofdependencyinjectedserviceinASP.NETCore3notbeingcalled【发布时间】:2020-06-1023:20:24【问题描述】:我阅读了IntroductiontoIdentityonASP.NETCore以在我的ASP.NETCore3Web应用... 查看详情

如何在 asp.net core 2.2 中实现 Cookie 基本身份验证和 jwt?

】如何在asp.netcore2.2中实现Cookie基本身份验证和jwt?【英文标题】:HowcaniimplementCookiebaseauthenticationandjwtinasp.netcore2.2?【发布时间】:2019-09-2907:52:12【问题描述】:我想在我的程序中同时使用基于cookie的身份验证和jwt,使用身份验... 查看详情

没有身份的 ASP.NET Core 2.0 承载身份验证

】没有身份的ASP.NETCore2.0承载身份验证【英文标题】:ASP.NETCore2.0BearerAuthwithoutIdentity【发布时间】:2018-01-2416:55:17【问题描述】:当我一天前开始在.NETcore2.0上实现一个独立的承载身份验证webapi时,我以为我有一个非常简单的目... 查看详情

在 ASP.NET Core 中使用多个身份验证方案

】在ASP.NETCore中使用多个身份验证方案【英文标题】:UsingmultipleauthenticationschemesinASP.NETCore【发布时间】:2017-10-0316:31:39【问题描述】:我有使用ASP.NETCore开发的WebAPI,我需要能够为同一服务使用基本和不记名身份验证方案。由于... 查看详情

ASP.NET Core 中基于令牌的身份验证(刷新)

】ASP.NETCore中基于令牌的身份验证(刷新)【英文标题】:TokenBasedAuthenticationinASP.NETCore(refreshed)【发布时间】:2015-08-1307:42:52【问题描述】:我正在使用ASP.NETCore应用程序。我正在尝试实现基于令牌的身份验证,但不知道如何使... 查看详情

asp.netcore同时支持多种认证方式|swagger支持(代码片段)

前言上次,我们实现了《ASP.NETCore同时支持多种认证方式》:services.AddAuthentication()    .AddDemoAuthentication(options =>  )    .AddJwtBearer(options =>            ...    );我们还希望为Swagger也添加多种认证支 查看详情

理解asp.netcore

...击此处查看全文目录之前,我们已经了解了ASP.NETCore中的身份认证,现在,我们来聊一下授权。老规矩,示例程序源码XXTk.Auth.Samples已经提交了,需要的请自取。概述ASP.NETCore中的授权方 查看详情

netcore体系-web应用程序-4asp.netcore2.0项目实战-13基于onactionexecuting全局过滤器,页面操作权限过滤控制到按钮级(代码片段)

...理  权限管理的基本定义:百度百科。  基于《Asp.NetCore2.0项目实战(10)基于cookie登录授权认证并实现前台会员、后台管理员同时登录》我们做过了登录认证,登录是权限的最基础的认证,没有登录就没有接下来的各种操... 查看详情

快速理解asp.netcore的认证与授权(代码片段)

ASP.NETCore的认证与授权已经不是什么新鲜事了,微软官方的文档对于如何在ASP.NETCore中实现认证与授权有着非常详细深入的介绍。但有时候在开发过程中,我们也往往会感觉无从下手,或者由于一开始没有进行认证授... 查看详情

core身份认证

Core中实现一个基础的身份认证注:本文提到的代码示例下载地址> HowtoachieveabasicauthorizationinASP.NETCore如何在ASP.NETCore中实现一个基础的身份认证ASP.NET终于可以跨平台了,但是不是我们常用的ASP.NET,而是叫一个ASP.NETCore的新平... 查看详情

asp.netcore系列48identity身份模型自定义(代码片段)

原文:asp.netcore系列48Identity身份模型自定义一.概述  ASP.NETCoreIdentity提供了一个框架,用于管理和存储在ASP.NETCore应用中的用户帐户。 Identity添加到项目时单个用户帐户选择作为身份验证机制。 默认情况下,Identity可以使... 查看详情

ASP.NET Core 5.0 WebAPI 中的多种身份验证方案

】ASP.NETCore5.0WebAPI中的多种身份验证方案【英文标题】:MultipleauthenticationschemesinASP.NETCore5.0WebAPI【发布时间】:2022-01-0408:19:03【问题描述】:我有一整套在.NET5.0中开发的(ASP.NETCore)WebAPI,并实现了Cookie和OpenIdConnect身份验证方案。... 查看详情