今天给大家分享在Web API下,如何利用ASP.NET Identity实现基本认证(Basic Authentication),在博客园子搜索了一圈Web API的基本认证,基本都是做的Forms认证,很少有Claims认证(声明式认证),而我们在用ASP.NET Identity实现登录,认证,授权的时候采用的是Claims认证。
在Web API2.0中认证接口为IAuthenticationFilter,我们只需实现该接口就行。创建BasicAuthenticationAttribute抽象基类,实现IAuthenticationFilter接口:

1 public abstract class BasicAuthenticationAttribute : Attribute, IAuthenticationFilter 2 { 3 protected abstract Task<IPrincipal> AuthenticateAsync(string userName, string password, HttpAuthenticationContext context, 4 CancellationToken cancellationToken); 5 public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken) 6 { 7 context.Principal = null; 8 AuthenticationHeaderValue authenticationHeader = context.Request.Headers.Authorization; 9 if (authenticationHeader != null && authenticationHeader.Scheme == "Basic") 10 { 11 if (!string.IsNullOrEmpty(authenticationHeader.Parameter)) 12 { 13 Tuple<string, string> data = GetUserNameAndPassword(authenticationHeader.Parameter); 14 context.Principal = await AuthenticateAsync(data.Item1, data.Item2,context, cancellationToken); 15 } 16 } 17 18 if (context.Principal == null) 19 { 20 context.ErrorResult = new UnauthorizedResult(new[] {new AuthenticationHeaderValue("Basic")}, 21 context.Request); 22 } 23 } 24 public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken) 25 { 26 return Task.FromResult(0); 27 } 28 public bool AllowMultiple 29 { 30 get { return false; } 31 } 32 private Tuple<string, string> GetUserNameAndPassword(string authenticationParameter) 33 { 34 if (!string.IsNullOrEmpty(authenticationParameter)) 35 { 36 var data = Encoding.ASCII.GetString(Convert.FromBase64String(authenticationParameter)).Split(':'); 37 return new Tuple<string, string>(data[0], data[1]); 38 } 39 return null; 40 } 41 }
其中Task<IPrincipal> AuthenticateAsync(string userName, string password, HttpAuthenticationContext context, CancellationToken cancellationToken)方法为抽象方法,用户可以重载实现自己的认证方式,Forms认证,Windows认证,Claims认证等等都可以。
AuthenticationHeaderValue authenticationHeader= context.Request.Headers.Authorization用于获取HTTP请求头部的认证信息。
authenticationHeader.Scheme == "Basic"用于指定认证模式为基本认证。
authenticationHeader.Parameter用户获取用户加密过后的用户名和密码。
如果认证不为空,且是Basic认证,头部参数不为空,则调用认证的具体代码,如果认证不通过,则调用HTTP认证上下文的ErroResult属性:
context.ErrorResult = new UnauthorizedResult(new[] {new AuthenticationHeaderValue("Basic")},context.Request);设置了该属性,浏览器则自动弹出用户登录的窗口。要想浏览器自动弹出登录窗口,必须在WebApiConfig配置类中指定令牌身份验证,即调用如下代码:config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));否则无法弹出登录窗体。
Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)方法在认证通过成功和失败后都会调用此方法,你可以在这里实现自己想要的逻辑,比如设置context.ErrorResult属性,在这里就不做处理了,因为AuthenticateAsync方法已经做了处理了。
GetUserNameAndPassword方法用于处理加密过后的用户名和密码。
接下来就是实现自己的认证逻辑了,这里采用Asp.net Identity的Claims认证。

1 public class IdentityBasicAuthenticationAttribute : BasicAuthenticationAttribute 2 { 3 protected override async Task<IPrincipal> AuthenticateAsync(string userName, string password, 4 HttpAuthenticationContext context, CancellationToken cancellationToken) 5 { 6 IPrincipal principal = null; 7 var userManager = context.Request.GetOwinContext().GetUserManager<AppUserManager>(); 8 var user = await userManager.FindAsync(userName, password); 9 if (user != null) 10 { 11 ClaimsIdentity identity = 12 await userManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie); 13 ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(identity); 14 principal = claimsPrincipal; 15 } 16 return principal; 17 } 18 }
var userManager = context.Request.GetOwinContext().GetUserManager<AppUserManager>()用于当前的用户管理器,用户的增删改查操作都依赖于此对象。
var user = await userManager.FindAsync(userName, password)用户根据用户名和密码找到用户。
ClaimsIdentity identity = await userManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie)创建用户,然后 通过ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(identity)创建声明,并且返回认证类型。
至于如何创建UserManager,如何通过Entityframwork来生成Asp.net Identity用户,角色和认证相关表,这里就不多说了,园子里面多的去了。
记得在登录代码中把用户名和密码加密后放到Cookie中,登陆后,在访问某个需要认证的Action时候记得在HTTP请求头部中写入Cookie信息,这样认证的Filter才能取到用户信息,登录创建Cookie代码片段如下:
1 2 3 4 5 6 7 | CookieHeaderValue cookie = new CookieHeaderValue( "userToken" , authorization) { Path = "/" , Domain = Request.RequestUri.Host, Expires = DateTimeOffset.Now.AddDays(7) }; responseMessage.Headers.AddCookies( new [] {cookie}); |
客户短AJax调用需要验证的Action方法如下:
1 2 3 4 5 6 7 8 9 10 | function ajaxOp(url, type, data) { $.ajax({ url: url, type: type, data: data, beforeSend: function(xhr) { xhr.setRequestHeader( 'Authorization' , 'Basic ' + $.cookie( "userToken" )); } }); } |
其中 beforeSend: function(xhr) {xhr.setRequestHeader('Authorization', 'Basic ' + $.cookie("userToken"))属性设置用于获取Cookie信息放到请求头部。
需要调用的Action记得加上 [IdentityBasicAuthentication]特性。
好了,就到这里吧。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?