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 = )
{
if (account == null)
throw new ArgumentNullException("account"); //序列化account对象
string accountJson = JsonConvert.SerializeObject(account);
//创建用户票据
var ticket = new FormsAuthenticationTicket(, 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 > )
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 = ,
Roles = new List<int>() { , , }
};
HttpFormsAuthentication.SetAuthenticationCoolie(account, rememberMe ? : );
if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > && 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());
}
}

【3】.net MVC 使用IPrincipal进行Form登录即权限验证的更多相关文章

  1. 从零开始实现asp.net MVC4框架网站的用户登录以及权限验证模块 详细教程

    从零开始实现asp.net MVC4框架网站的用户登录以及权限验证模块 详细教程   用户登录与权限验证是网站不可缺少的一部分功能,asp.net MVC4框架内置了用于实现该功能的类库,只需要简单搭 ...

  2. ASP.NET MVC View 和 Web API 的基本权限验证

    ASP.NET MVC 5.0已经发布一段时间了,适应了一段时间,准备把原来的MVC项目重构了一遍,先把基本权限验证这块记录一下. 环境:Windows 7 Professional SP1 + Mi ...

  3. Spring MVC 使用拦截器优雅地实现权限验证功能

    在上一篇 SpringAOP 实现功能权限校验功能 中虽然用AOP通过抛异常,请求转发等勉强地实现了权限验证功能,但感觉不是那么完美,应该用拦截器来实现才是最佳的,因为拦截器就是用来拦截请求的,在请求 ...

  4. django-个人博客登录及权限验证功能的实现

    完成注册后随即开始进行登录,登录后页面显示登录者的名称 实现如下: 前端页面html,对session进行判断,有值则显示登录者的名字 ,无值则显示注册字样: 后台views函数  首先对验证码进行验 ...

  5. [Java]利用拦截器和自定义注解做登录以及权限验证

    1.自定义注解 需要验证登录的注解 package com.etaofinance.wap.common; import java.lang.annotation.Documented; import ...

  6. php的api及登录的权限验证

    类,库,接口(APi),函数,这些概念都是根据问题规模的大小来界定的.一个很小的问题肯定没有必要写成一个库,只需要写几句话就行了. 但是比如一个登录验证,这个功能很强大,很通用,可能前台后台都需要用到 ...

  7. spring boot:spring security整合jwt实现登录和权限验证(spring boot 2.3.3)

    一,为什么使用jwt? 1,什么是jwt? Json Web Token, 它是JSON风格的轻量级的授权和身份认证规范, 可以实现无状态.分布式的Web应用授权 2,jwt的官网: https:// ...

  8. C# MVC 页面面包屑以及相应的权限验证操作

    一.特性类 /// <summary> /// 访问权限控制属性. /// </summary> [AttributeUsage(AttributeTargets.Method ...

  9. Web用户的身份验证及WebApi权限验证流程的设计和实现 asp.net mvc AllowAnonymous 不起作用, asp.net mvc 匿名访问

    原文地址: https://blog.csdn.net/zjlovety/article/details/17095627 前言:Web 用户的身份验证,及页面操作权限验证是B/S系统的基础功能,一个 ...

随机推荐

  1. “全栈2019”Java第六十九章:内部类访问外部类成员详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  2. PHP 执行系统外部命令的方法 system() exec()

    PHP作为一种服务器端的脚本语言,像编写简单.或者是复杂的动态网页这样的任务,它完全能够胜任.但事情不总是如此,有时为了实现某个功能,必须借助于操作系统的外部程序(或者称之为命令),这样可以做到事半功 ...

  3. uC/OS-II 函数之任务相关函数

    获得更多资料欢迎进入我的网站或者 csdn或者博客园 对于有热心的小伙伴在微博上私信我,说我的uC/OS-II 一些函数简介篇幅有些过于长应该分开介绍.应小伙伴的要求,特此将文章分开进行讲解.上文主要 ...

  4. P3866 [TJOI2009]战争游戏 最小割

    $ \color{#0066ff}{ 题目描述 }$ 小R正在玩一个战争游戏.游戏地图是一个M行N列的矩阵,每个格子可能是障碍物,也可能是空地,在游戏开始时有若干支敌军分散在不同的空地格子中.每支敌军 ...

  5. python cookbook

    一 .数据结构 python collections包中 deque :固定长度队列,(例如固定长度的cache什么的) defaultdict:如果每个键值不存在,默认返回值 orderdict:有 ...

  6. mysql5.1解压版安装

    1.如果已经安装别的版本先卸载干净,cmd管理员权限登录,mysql\bin目录:mysqld -remove 2.环境变量 MYSQL:path 3.my.ini [mysqld]port=3306 ...

  7. Windows环境安装Elasticsearch

    安装前提: 确保电脑已经安装了JDK,要求在1.8以上,并且安装目录不能包括空格 下载 下载地址:https://www.elastic.co/cn/downloads/elasticsearch 选 ...

  8. 1.使用frp穿透内网

    1.前因后果 1.1弃用ngrok 为节约服务器成本,花了500多块买了一个华为云得1G 1核心 5M得云服务器.然后用ngrok来穿透内网.一直用得还  但是今天在弄nginx得时候发现 ngrok ...

  9. python学习 条件控制

    if - else  if 条件a : 内容a else : 内容 非a if - elif - else  if 条件a : 内容a elif 条件b: 内容b-a else : 内容 非(a∪b) ...

  10. thinkPhP + Apache + PHPstorm整合框架

    最近在学习使用 ThinkPhP,网上很多都是用一些整合好的服务框架,为了学习,在这里我简单的对Apache.PHP做一个原生的整合,希望对你有帮助. 步骤: ①下载 thinkPHP.PHP.Apa ...