作者:手机用户2602925995 | 来源:互联网 | 2022-01-22 02:05
.net MVC使用IPrincipal进行Form登录即权限验证,供大家参考,具体内容如下
1.在MVC项目中添加用户类,可以根据实际项目需求添加必要属性
public class UserData
{
///
/// ID
///
public int UserId { get; set; }
///
/// 用户名
///
public string UserName { get; set; }
///
/// 角色ID列表
///
public List Roles { get; set; }
}
2.添加类Principal实现IPrincipal接口
public class Principal : IPrincipal
{
public IIdentity Identity { get; private set;}
public UserData Account { get; set; }
///
/// 构造函数
///
///
///
public Principal(FormsAuthenticationTicket ticket, UserData account)
{
if (ticket == null)
throw new ArgumentNullException("ticket");
if (account == null)
throw new ArgumentNullException("UserData");
this.Identity = new FormsIdentity(ticket);
this.Account = account;
}
public bool IsInRole(string role)
{
if (string.IsNullOrEmpty(role))
return true;
if (this.Account == null || this.Account.Roles == null)
return false;
return role.Split(',').Any(q => Account.Roles.Contains(int.Parse(q)));
}
}
IPrincipal接口有对象Identity已经需要实现验证角色方法IsInRole()。在我们的实现类中添加了"用户信息(UserData)"属性Account。
构造函数中进行了初始化,第一个对象为Form验证的票据对象,下面ticket会携带用户信息一起保存进COOKIE中。
3.创建存储COOKIE和读取COOKIE的类
///
/// 写入COOKIE和读取COOKIE
///
public class HttpFormsAuthentication
{
//将用户信息通过ticket加密保存到COOKIE
public static void SetAuthenticationCoolie(UserData account, int rememberDay = 0)
{
if (account == null)
throw new ArgumentNullException("account");
//序列化account对象
string accountJson = JsonConvert.SerializeObject(account);
//创建用户票据
var ticket = new FormsAuthenticationTicket(1, account.UserName, DateTime.Now, DateTime.Now.AddDays(rememberDay), false, accountJson);
//加密
string encryptAccount = FormsAuthentication.Encrypt(ticket);
//创建COOKIE
var COOKIE = new HttpCOOKIE(FormsAuthentication.FormsCOOKIEName, encryptAccount)
{
HttpOnly= true,
Secure = FormsAuthentication.RequireSSL,
Domain = FormsAuthentication.COOKIEDomain,
Path = FormsAuthentication.FormsCOOKIEPath
};
if (rememberDay > 0)
COOKIE.Expires = DateTime.Now.AddDays(rememberDay);
//写入COOKIE
HttpContext.Current.Response.COOKIEs.Remove(COOKIE.Name);
HttpContext.Current.Response.COOKIEs.Add(COOKIE);
}
//获取COOKIE并解析出用户信息
public static Principal TryParsePrincipal(HttpContext context)
{
if (cOntext== null)
throw new ArgumentNullException("context");
HttpRequest request = context.Request;
HttpCOOKIE COOKIE = request.COOKIEs[FormsAuthentication.FormsCOOKIEName];
if (COOKIE == null || string.IsNullOrEmpty(COOKIE.Value))
{
return null;
}
//解密coolie值
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(COOKIE.Value);
UserData account = JsonConvert.DeserializeObject(ticket.UserData);
return new Principal(ticket, account);
}
}
存储COOKIE时将用户信息序列化后的字符串accountJson由ticket其携带加密后保存入COOKIE中,具体的accountJson被赋值给FormsAuthenticationTicket的UserData属性。
可看到解析时将ticket.UserData反序列化后得到了原始的用户信息对象,然后生成Principal对象。
解析COOKIE得到Principal对象的方法TryParsePrincipal,下面会在发起请求时用到,而返回的Principal对象被赋值给HttpContext.User。
4.在Global.asax中注册Application_PostAuthenticateRequest事件,保证权限验证前将COOKIE中的用户信息取出赋值给User
protected void Application_PostAuthenticateRequest(object sender, System.EventArgs e)
{
HttpContext.Current.User =
HttpFormsAuthentication.TryParsePrincipal(HttpContext.Current);
}
5.集成AuthorizeAttribute特性类并重写AuthorizeCore,HandleUnauthorizedRequest方法
public class FormAuthorizeAttribute : AuthorizeAttribute
{
///
/// 先进入此方法,此方法中会调用 AuthorizeCore 验证逻辑,验证不通过会调用 HandleUnauthorizedRequest 方法
///
///
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
}
///
/// 权限验证
///
///
///
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var user = httpContext.User as Principal;
if (user != null)
return user.IsInRole(base.Roles);
return false;
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
//验证不通过,直接跳转到相应页面,注意:如果不是哟娜那个以下跳转,则会继续执行Action方法
filterContext.Result = new RedirectResult("~/Login/Index");
}
}
AuthorizeCore与HandleUnauthorizedRequest方法均是在方法OnAuthorization中调用,AuthorizeCore验证不通过才会调用HandleUnauthorizedRequest方法。
将验证代码在AuthorizeCore中实现,验证不通过的逻辑在HandleUnauthorizedRequest方法中实现。
6.添加LoginController实现登录逻辑
namespace MVCAuthorizeTest.Controllers
{
public class LoginController : Controller
{
[AllowAnonymous]
// GET: Login
public ActionResult Index(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return View();
}
[HttpPost]
[AllowAnonymous]
public ActionResult Index(string name, string password, bool rememberMe, string returnUrl)
{
var account = new UserData()
{
UserName = name,
UserId = 110,
Roles = new List() { 1, 2, 3 }
};
HttpFormsAuthentication.SetAuthenticationCoolie(account, rememberMe ? 7 : 0);
if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/") && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
// POST: /Account/LogOff
[HttpPost]
public ActionResult LogOff()
{
System.Web.Security.FormsAuthentication.SignOut();
return RedirectToAction("Index", "Home");
}
}
}
7.对需要验证的controller或action添加特性标签
[FormAuthorize(Roles = "1,2")]
public class HomeController : Controller
{
[FormAuthorize]
public ActionResult Index()
{
return View();
}
}
如图
8.在添加FilterConfig中添加全局注册filter,减少每个action分别设置。如果有不需要验证的页面,添加[AllowAnonymous]特性即可
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
//全局注册filter
filters.Add(new FormAuthorizeAttribute());
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。