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

  

  

  

posted @ 2021-11-22 19:45  zq爱生活爱代码  阅读(49)  评论(0编辑  收藏  举报