HttpClient 调用Form验证下的WepApi
开始Form认证,拒绝匿名登录
<system.web> <compilation debug="true" targetFramework="4.5" /> <httpRuntime targetFramework="4.5" /> <authentication mode="Forms"> <forms loginUrl="~/account/login"/> </authentication> <authorization> <deny users="?"/> </authorization> </system.web>
//认证对象实体
using System; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Web; namespace WebApi.Models { public class Credential { [DisplayName("用户名")] [Required] public string UserName { get; set; } [DisplayName("密码")] [Required] [DataType(DataType.Password)] public string Password { get; set; } } }
账号验证Controller
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Mvc; using System.Web.Security; using WebApi.Models; namespace WebApi.Controllers { public class AccountController : Controller { static Dictionary<string,string> userAccounts; static AccountController() { userAccounts = new Dictionary<string,string>(StringComparer.OrdinalIgnoreCase); userAccounts.Add("Foo","Password"); userAccounts.Add("Bar","Password"); userAccounts.Add("Baz","Password"); } public ActionResult Login() { return View(new Credential()); } [HttpPost] public ActionResult Login(Credential loginInfo, string returnUrl) { if (!ModelState.IsValid) { return View(); } string password; if (userAccounts.TryGetValue(loginInfo.UserName, out password)) { if (password == loginInfo.Password) { FormsAuthentication.SetAuthCookie(loginInfo.UserName, false); if(string.IsNullOrEmpty(returnUrl)) { return new HttpStatusCodeResult(HttpStatusCode.OK); } return Redirect(returnUrl); } ModelState.AddModelError("Password", "密码不正确"); } else { ModelState.AddModelError("UserName", "用户名不存在"); } return View(); } } }
最关键的调用代码,首先验证账号,获取Server 添加Header的Cookie
然后本地http请求,添加之前请求回来的cookie value。
验证结果是获取Cookie Value,可以模拟Form请求
同时通过FormUrlEncodedContent模拟application/x-www-form-urlencoded对主题内容进行编码
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Text; using System.Threading.Tasks; namespace Client { class Program { static void Main(string[] args) { string token = GetSecurityToken("Foo", "Password", "http://localhost:2303/account/login", ".ASPXAUTH"); string address = "http://localhost:2303/api/demo"; if (!string.IsNullOrEmpty(token)) { HttpClientHandler handler = new HttpClientHandler { CookieContainer = new CookieContainer() }; handler.CookieContainer.Add(new Uri(address), new Cookie(".ASPXAUTH", token)); using (HttpClient httpClient = new HttpClient(handler)) { HttpResponseMessage response = httpClient.GetAsync(address).Result; IEnumerable<string> userNames = response.Content.ReadAsAsync<IEnumerable<string>>().Result; foreach (string userName in userNames) { Console.WriteLine(userName); } } } Console.ReadKey(); } private static string GetSecurityToken(string userName, string password, string url, string cookieName) { using (HttpClient httpClient = new HttpClient()) { Dictionary<string, string> credential = new Dictionary<string, string>(); credential.Add("UserName", userName); credential.Add("Password", password); HttpResponseMessage response = httpClient.PostAsync(url, new FormUrlEncodedContent(credential)).Result; IEnumerable<string> cookies; if (response.Headers.TryGetValues("Set-Cookie", out cookies)) { string token = cookies.FirstOrDefault(value => value.StartsWith(cookieName)); if (null == token) { return null; } return token.Split(';')[0].Substring(cookieName.Length + 1); } return null; } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Threading; using System.Web; using System.Web.Http; namespace WebApi.Controllers { public class DemoController : ApiController { public IEnumerable<string> GetUsers() { yield return HttpContext.Current.User.Identity.Name; yield return Thread.CurrentPrincipal.Identity.Name; yield return this.User.Identity.Name; } } }