ASP.NET Web api 身份认证原理解析
程序员文章站
2024-02-29 10:02:58
...
类图:
TestController.cs
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web;
using System.Web.Http;
using System.Web.Security;
using WebApiAuthentication.Core;
namespace WebApiAuthentication.Controllers
{
[RoutePrefix("Test")]
public class TestController : ApiController
{
[Route("SignIn")]
[HttpGet]
public IHttpActionResult SignIn()
{
MyFormsAuthenticationTicket ticket = new MyFormsAuthenticationTicket(2, new Random().Next().ToString(), DateTime.Now, DateTime.Now.AddDays(1), true, "admin,张三");
string encryptStr = MyFormsAuthentication.EncryptDES(JsonConvert.SerializeObject(ticket), "11111111");
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptStr);
//cookie.HttpOnly = true;
cookie.Secure = FormsAuthentication.RequireSSL;
HttpContext context = HttpContext.Current;
if (context == null)
throw new InvalidOperationException();
// 写入Cookie
context.Response.Cookies.Remove(cookie.Name);
context.Response.Cookies.Add(cookie);
return Ok("登陆成功");
}
[Route("SignOut")]
[HttpGet]
[Authorize]
public IHttpActionResult SignOut()
{
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, "");
cookie.Expires = DateTime.Now.AddDays(-1);
HttpContext.Current.Response.Cookies.Add(cookie);
return Ok("退出成功");
}
/// <summary>
/// 测试是否登陆后可以访问
/// </summary>
/// <returns></returns>
[Route("TestSuccess")]
[HttpGet]
[Authorize]
public IHttpActionResult TestSuccess()
{
return Ok("访问成功");
}
/// <summary>
/// 测试指定角色
/// </summary>
/// <returns></returns>
[Route("TestRoles")]
[HttpGet]
[Authorize(Roles="找刘")]
public IHttpActionResult TestRoles()
{
return Ok("访问成功");
}
/// <summary>
/// 测试指定角色
/// </summary>
/// <returns></returns>
[Route("TestZhangsan")]
[HttpGet]
[Authorize(Roles = "张三")]
public IHttpActionResult TestZhangsan()
{
return Ok("访问成功");
}
}
}
MyFormsAuthenticationTicket.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
namespace WebApiAuthentication.Core
{
public class MyFormsAuthenticationTicket
{
public MyFormsAuthenticationTicket(int version, string name, DateTime issueDate, DateTime expiration, bool isPersistent, string userData)
{
this.Version = version;
this.Name = name;
this.Expiration = expiration;
this.IssueDate = issueDate;
this.IsPersistent = isPersistent;
this.UserData = userData;
this.CookiePath = FormsAuthentication.FormsCookiePath;
DtNow = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ssss");
}
public string CookiePath { get; set; }
public DateTime Expiration { get; set; }
public bool Expired { get; set; }
public bool IsPersistent { get; set; }
public DateTime IssueDate { get; set; }
public string Name { get; set; }
public string UserData { get; set; }
public int Version { get; set; }
public string DtNow { get; set; }
}
}
MyFormsAuthentication.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
namespace WebApiAuthentication.Core
{
public static class MyFormsAuthentication
{
/// <summary>
/// DES加密字符串
/// </summary>
/// <param name="encryptString">待加密的字符串</param>
/// <param name="encryptKey">加***,要求为8位</param>
/// <returns>加密成功返回加密后的字符串,失败返回源串</returns>
public static string EncryptDES(string encryptString, string key)
{
try
{
byte[] rgbKey = Encoding.UTF8.GetBytes(key);
byte[] rgbIV = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString);
DESCryptoServiceProvider dCSP = new DESCryptoServiceProvider();
MemoryStream mStream = new MemoryStream();
CryptoStream cStream = new CryptoStream(mStream, dCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
cStream.Write(inputByteArray, 0, inputByteArray.Length);
cStream.FlushFinalBlock();
return Convert.ToBase64String(mStream.ToArray());
}
catch
{
return encryptString;
}
}
/// <summary>
/// DES解密字符串
/// </summary>
/// <param name="decryptString">待解密的字符串</param>
/// <param name="key">解***,要求8位</param>
/// <returns></returns>
public static string DecryptDES(string decryptString, string key)
{
try
{
//默认**向量
byte[] Keys = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
byte[] rgbKey = Encoding.UTF8.GetBytes(key);
byte[] rgbIV = Keys;
byte[] inputByteArray = Convert.FromBase64String(decryptString);
DESCryptoServiceProvider DCSP = new DESCryptoServiceProvider();
MemoryStream mStream = new MemoryStream();
CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
cStream.Write(inputByteArray, 0, inputByteArray.Length);
cStream.FlushFinalBlock();
return Encoding.UTF8.GetString(mStream.ToArray());
}
catch
{
return decryptString;
}
}
}
}
DecryptHttpMoudle.cs
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
namespace WebApiAuthentication.Core
{
public class DecryptHttpMoudle : IHttpModule
{
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.AuthenticateRequest += Context_AuthenticateRequest;
}
/// <summary>
/// 替换HttpContext.Current.User实现
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Context_AuthenticateRequest(object sender, EventArgs e)
{
var app = sender as HttpApplication;
if (app == null)
{
app.Context.User = null;
return;
}
var cookie = HttpContext.Current.Request.Headers.GetValues("Cookie");
if (cookie == null)
{
app.Context.User = new MyPrincipal("",null);
return;
}
if (cookie.Count() < 1)
{
app.Context.User = new MyPrincipal("", null);
return;
}
MyFormsAuthenticationTicket ticket;
try
{
//获取cookie值的另一种方式,特殊符号会被省略
//var sdd = Request.Headers.GetCookies(FormsAuthentication.FormsCookieName).FirstOrDefault();
//var value=sdd[FormsAuthentication.FormsCookieName].Value;
string decryptStr = MyFormsAuthentication.DecryptDES(cookie[0].Substring(cookie[0].IndexOf('=') + 1), "11111111");
ticket = JsonConvert.DeserializeObject<MyFormsAuthenticationTicket>(decryptStr);
}
catch (Exception)
{
app.Context.User = new MyPrincipal("", null);
return;
}
if (ticket == null)
{
app.Context.User = new MyPrincipal("", null);
return;
}
app.Context.User = new MyPrincipal(ticket.Name,ticket.UserData);
}
}
}
MyPrincipal.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Web;
namespace WebApiAuthentication.Core
{
public class MyPrincipal : IPrincipal
{
private string[] m_roles;
public MyPrincipal(string name,string roles)
{
if (!string.IsNullOrEmpty(roles)) {
string[] rolesArr = roles.Split(',');
m_roles = new string[rolesArr.Count()];
for (int i = 0; i < rolesArr.Count(); i++)
{
m_roles[i] = rolesArr[i];
}
}
_identity = new MyIdentity(name);
}
private IIdentity _identity;
public IIdentity Identity
{
get
{
return _identity;
}
}
public bool IsInRole(string role)
{
if ((role == null) || (this.m_roles == null))
{
return false;
}
for (int i = 0; i < this.m_roles.Length; i++)
{
if ((this.m_roles[i] != null) && (string.Compare(this.m_roles[i], role, StringComparison.OrdinalIgnoreCase) == 0))
{
return true;
}
}
return false;
}
}
}
MyIdentity.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Web;
namespace WebApiAuthentication.Core
{
public class MyIdentity : IIdentity
{
public MyIdentity(string name) {
this.m_name = name;
this.m_type = "";
}
private string m_type;
private string m_name;
public string Name
{
get
{
return this.m_name;
}
}
public bool IsAuthenticated
{
get
{
return !this.m_name.Equals("");
}
}
public string AuthenticationType
{
get
{
return this.m_type;
}
}
}
}
Web.config
<system.webServer>
...
<!--配置文件里注册的HttpModules-->
<modules>
<add name="DecryptHttpMoudle" type="WebApiAuthentication.Core.DecryptHttpMoudle"/>
</modules>
</system.webServer>
运行结果如图:
上一篇: 框架之Spring-控制反转,依赖注入(IOC原理)
下一篇: PHP 接入支付宝即时到账功能