概览

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

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

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

 https://en.wikipedia.org/wiki/Basic_access_authentication
<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认证:

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

*
asp.netcore 添加认证中间件

*
注册认证中间件
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() );
 

客户端:

*  添加认证请求Handler
*  以上述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());
 

That's All .  BA认证是随处可见的基础认证协议,本文期待以最清晰的方式帮助你理解协议,最优雅的方式提供编程实践思路。

 

----------如有问题请大胆斧正;你觉得文章对你有价值,请或加关注,蟹蟹-----------~~。。~~------------

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:637538335
关注微信