WEBAPI AuthenticateAttribute 基于Basic 验证
如果验证失败,会返回 401 Unauthorized
并且通过 response.Headers.WwwAuthenticate 头信息 获取 AuthenticationHeaderValue ,从而获取 验证规则,以及服务器传的值
比如 在程序中 给头信息赋值 credential,client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(credential));
在验证 AuthenticateAsync 中通过 string credential = Encoding.Default.GetString(Convert.FromBase64String(headerValue.Parameter)); 来取值,进行判断
验证过后,过滤器会调用 ChallengeAsync 方法 ,获取验证的Principal,如果不为空且 验证有效,则不返回401 权限不通过提示
//IPrincipal user = context.ActionContext.ControllerContext.RequestContext.Principal;
IPrincipal user = Thread.CurrentPrincipal;
using System; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Text; namespace Client { class Program { static void Main(string[] args) { Console.OutputEncoding = Encoding.UTF8; HttpClient client = new HttpClient(); HttpResponseMessage response = client.GetAsync("http://localhost:3721/api/demo").Result; if (response.StatusCode == HttpStatusCode.Unauthorized) { Console.WriteLine("认证失败"); AuthenticationHeaderValue challenge = response.Headers.WwwAuthenticate.FirstOrDefault(); if (challenge != null && challenge.Scheme == "Basic") { Console.Write("输入用户名:"); string userName = Console.ReadLine().Trim(); Console.Write("输入密码:"); string password = Console.ReadLine().Trim(); byte[] credential = Encoding.Default.GetBytes(string.Format("{0}:{1}", userName, password)); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(credential)); response = client.GetAsync("http://localhost:3721/api/demo").Result; string result = response.Content.ReadAsAsync<string>().Result; Console.WriteLine(result); } } Console.ReadLine(); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Net.Http.Headers; using System.Security.Principal; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Web; using System.Web.Http; using System.Web.Http.Filters; using System.Web.Http.Results; namespace WebApi { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class AuthenticateAttribute : FilterAttribute, IAuthenticationFilter { private static Dictionary<string, string> userAccounters; static AuthenticateAttribute() { userAccounters = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); userAccounters.Add("Foo", "Password"); userAccounters.Add("Bar", "Password"); userAccounters.Add("Baz", "Password"); } public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken) { IPrincipal user = null; AuthenticationHeaderValue headerValue = context.Request.Headers.Authorization; if (null != headerValue && headerValue.Scheme == "Basic") { string credential = Encoding.Default.GetString(Convert.FromBase64String(headerValue.Parameter)); string[] split = credential.Split(':'); if (split.Length == 2) { string userName = split[0]; string password; if (userAccounters.TryGetValue(userName, out password)) { if (password == split[1]) { GenericIdentity identity = new GenericIdentity(userName); user = new GenericPrincipal(identity, new string[0]); } } } } context.Principal = user; return Task.FromResult<object>(null); } public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken) { IPrincipal user = context.ActionContext.ControllerContext.RequestContext.Principal; if (null == user || !user.Identity.IsAuthenticated) { string parameter = string.Format("realm=\"{0}\"", context.Request.RequestUri.DnsSafeHost); AuthenticationHeaderValue challenge = new AuthenticationHeaderValue("Basic", parameter); context.Result = new UnauthorizedResult(new AuthenticationHeaderValue[] { challenge }, context.Request); } return Task.FromResult<object>(null); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; namespace WebApi.Controllers { [Authenticate] public class DemoController : ApiController { public string Get() { return "成功调用!"; } } }