.net MVC使用IPrincipal进行Form登录即权限验证(3)

.net MVC使用IPrincipal进行Form登录即权限验证,供大家参考,具体内容如下

1.在MVC项目中添加用户类,可以根据实际项目需求添加必要属性

public class UserData

{

/// <summary>

/// ID

/// </summary>

public int UserId { get; set; }

/// <summary>

/// 用户名

/// </summary>

public string UserName { get; set; }

/// <summary>

/// 角色ID列表

/// </summary>

public List<int> Roles { get; set; }

}

2.添加类Principal实现IPrincipal接口

public class Principal : IPrincipal

{

public IIdentity Identity { get; private set;}

public UserData Account { get; set; }

/// <summary>

/// 构造函数

/// </summary>

/// <param name="ticket"></param>

/// <param name="account"></param>

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的类

/// <summary>

/// 写入cookie和读取cookie

/// </summary>

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<UserData>(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

{

/// <summary>

/// 先进入此方法,此方法中会调用 AuthorizeCore 验证逻辑,验证不通过会调用 HandleUnauthorizedRequest 方法

/// </summary>

/// <param name="filterContext"></param>

public override void OnAuthorization(AuthorizationContext filterContext)

{

base.OnAuthorization(filterContext);

}

/// <summary>

/// 权限验证

/// </summary>

/// <param name="httpContext"></param>

/// <returns></returns>

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<int>() { 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());

}

}

以上是 .net MVC使用IPrincipal进行Form登录即权限验证(3) 的全部内容, 来源链接: utcz.com/z/313297.html

回到顶部