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;
}
}
}

浙公网安备 33010602011771号