使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的:

  1. 客户端使用用户名跟密码请求登录
  2. 服务端收到请求,去验证用户名与密码
  3. 验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
  4. 客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
  5. 客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
  6. 服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据

一,用户点击登录时 对用户名密码进行检查。 当状态为Success   进而通过用户名密码去生成一个身份验证的令牌

从而对令牌进行加密 生成Token  然后放入Cookie里

        public ActionResult Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
} LoginManager loginManager = new LoginManager();
var result = loginManager.SignIn(model.Email, model.Password);
if (result == LoginState.Success)
{
var role = loginManager.GetUserRoleByEmailAsync(model.Email); //通过用户名(邮箱) 密码生成一个ticket令牌
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(, model.Email, DateTime.Now,
DateTime.Now.AddMinutes(), true, string.Format("{0}&{1}", model.Email, model.Password)); //加密
var Token = FormsAuthentication.Encrypt(ticket); System.Web.HttpContext.Current.Session["UserName"]=model.Email;
System.Web.HttpContext.Current.Session["Role"] = role; //将Token加入到cookie 并设置为5天过期
var cookie = new HttpCookie("Token", Token)
{
Expires = DateTime.Now.AddDays()
};
Response.Cookies.Add(cookie); if (returnUrl != null)
{
return Redirect(returnUrl);
}
return Redirect("/Home/Chat");
} return View();
}

二,继承并重写 AuthorizeAttribute 中的 OnAuthorization

这里 我建了个XML文件用来存放action的角色权限

用来对方法访问的控制。  这里会解析token 然后进行匹配

<?xml version="1.0" encoding="utf-8" ?>
<Roles>
<Controller name="Home">
<Action name="Index"></Action>
<Action name="Chat">Admin,VIP5,VIP4</Action>
</Controller>
<Controller name="Account">
<Action name="Index"></Action>
<Action name="GETint">Admin,VIP5,VIP4</Action>
</Controller>
</Roles>
   public class MVCAuthorize : AuthorizeAttribute
{
public new string Roles { get; set; } //这个是从Action中传过来的角色
public override void OnAuthorization(AuthorizationContext actionContext)
{ var token = actionContext.HttpContext.Request.Params["Token"]; if (!string.IsNullOrEmpty(token))
{
string controllerName = actionContext.ActionDescriptor.ControllerDescriptor.ControllerName; //得到控制器名称
string actionName = actionContext.ActionDescriptor.ActionName;//得到Action名称
string roles = GetActionRoles(actionName, controllerName); // 在Xml文件中根据控制器 Action 找到对应的访问角色权限
if (!string.IsNullOrWhiteSpace(roles))
{
this.Roles = Roles + "," + roles;
var isAuthValidate = ValidateTicket(token, Roles);
if (isAuthValidate != AuthorizeState.ValidateSuucss)
{
base.HandleUnauthorizedRequest(actionContext);
} }
}
else{
             base.HandleUnauthorizedRequest(actionContext);
           }

        }

        //获取当前Action的访问角色
public static string GetActionRoles(string action, string controller)
{
XElement rootElement = XElement.Load(HttpContext.Current.Server.MapPath("/") + "/XML/RoleAction.xml");
XElement controllerElement = findElementByAttribute(rootElement, "Controller", controller);
if (controllerElement != null)
{
XElement actionElement = findElementByAttribute(controllerElement, "Action", action);
if (actionElement != null)
{
return actionElement.Value;
}
}
return "";
} public static XElement findElementByAttribute(XElement xElement, string tagName, string attribute)
{
return xElement.Elements(tagName).FirstOrDefault(x => x.Attribute("name").Value.Equals(attribute, StringComparison.OrdinalIgnoreCase));
} //校验用户名密码(对Session匹配,或数据库数据匹配)
private AuthorizeState ValidateTicket(string encryptToken,string role)
{
if (encryptToken == null)
{
return AuthorizeState.TokenErro;
}
//解密Ticket
var strTicket = FormsAuthentication.Decrypt(encryptToken).UserData; //从Ticket里面获取用户名和密码
var index = strTicket.IndexOf("&");
string userName = strTicket.Substring(, index);
string password = strTicket.Substring(index + );
ArrayList arrayList = new ArrayList(role.Split(','));
var roleName = HttpContext.Current.Session["Role"].ToString();
var name = HttpContext.Current.Session["UserName"].ToString();
//取得session,不通过说明用户退出,或者session已经过期
if (arrayList.Contains(roleName) && name == userName) //获取对应控制器 对应方法的访问角色权限 如果包含说明符合访问 否则返回权限错误
{
return AuthorizeState.ValidateSuucss;
}
else
{
return AuthorizeState.UserValidateErro;
}
}
}

当我们去访问这个方法时。他会先进行身份验证。进入MVCAuthorize中。 这里你可以扩展开来。 比如我临时需要对这个方法在多开放些角色 ,可以直接在action 带上

        [MVCAuthorize(Roles = "VIP9,ActiveUser")]
public ActionResult Chat()
{ var account = HttpContext.User.Identity.Name;
ModelDBContext db = new ModelDBContext();
//ViewBag.UserName =db.User.Where(x=>x.Email == account).FirstOrDefault().FullName;
return View();
}

当检测到用户未登陆 。 没有通过认证的同时 去访问的话。  会返回一个401 你没有当前页面权限访问

然后就是通过验证后的样子

常常是看别人怎么实现。 还是自己多去实践 才能成长更快。 加油

工作之余。手撸代码。颇有漏洞。望君批正。

玩一玩基于Token的 自定义身份认证+权限管理的更多相关文章

  1. 基于token的后台身份验证(转载)

    几种常用的认证机制 HTTP Basic Auth HTTP Basic Auth简单点说明就是每次请求API时都提供用户的username和password,简言之,Basic Auth是配合RES ...

  2. 在ASP.NET Web API 2中使用Owin基于Token令牌的身份验证

    基于令牌的身份验证 基于令牌的身份验证主要区别于以前常用的常用的基于cookie的身份验证,基于cookie的身份验证在B/S架构中使用比较多,但是在Web Api中因其特殊性,基于cookie的身份 ...

  3. 在ASP.NET Core中实现一个Token base的身份认证

    注:本文提到的代码示例下载地址> How to achieve a bearer token authentication and authorization in ASP.NET Core 在 ...

  4. [转]NET Core中实现一个Token base的身份认证

    本文转自:http://www.cnblogs.com/Leo_wl/p/6077203.html 注:本文提到的代码示例下载地址> How to achieve a bearer token ...

  5. 基于Token的WEB后台认证机制

    几种常用的认证机制 HTTP Basic Auth HTTP Basic Auth简单点说明就是每次请求API时都提供用户的username和password,简言之,Basic Auth是配合RES ...

  6. NET Core中实现一个Token base的身份认证

    NET Core中实现一个Token base的身份认证 注:本文提到的代码示例下载地址> How to achieve a bearer token authentication and au ...

  7. .NetCore WebApi——基于JWT的简单身份认证与授权(Swagger)

    上接:.NetCore WebApi——Swagger简单配置 任何项目都有权限这一关键部分.比如我们有许多接口.有的接口允许任何人访问,另有一些接口需要认证身份之后才可以访问:以保证重要数据不会泄露 ...

  8. 【转】基于Token的WEB后台认证机制

    原谅地址:http://www.cnblogs.com/xiekeli/p/5607107.html 几种常用的认证机制 HTTP Basic Auth HTTP Basic Auth简单点说明就是每 ...

  9. springboot结合jwt实现基于restful接口的身份认证

    基于restful接口的身份认证,可以采用jwt的方式实现,想了解jwt,可以查询相关资料,这里不做介绍~ 下面直接看如何实现 1.首先添加jwt的jar包,pom.xml中添加依赖包: <de ...

随机推荐

  1. VB求最大公约数的两个例子

    VB求最大公约数的两个算法 Private Sub Command1_Click() Dim a As Long, b As Long a = InputBox("请输入要求最大公约数的整数 ...

  2. 上传到 App Store 时出错。

      Try this, it fixed it for me. Open Terminal and run: cd ~ mv .itmstransporter/ .old_itmstransporte ...

  3. 测试&标准说明文章

    这是一篇测试用文章,主要想想怎么把纸质本上的习惯沿袭到博客上来 #coding=utf-8 import sys def main(): print "this is some code f ...

  4. Spring Boot with Spring-Data-JPA学习案例

    0x01 什么是Spring Boot? Spring Boot是用来简化Spring应用初始搭建以及开发过程的全新框架,被认为是Spring MVC的"接班人",和微服务紧密联系 ...

  5. Spring Boot 入门教程

    Spring Boot 入门教程,包含且不仅限于使用Spring Boot构建API.使用Thymeleaf模板引擎以及Freemarker模板引擎渲染视图.使用MyBatis操作数据库等等.本教程示 ...

  6. Oracle profile 使用技巧

    给scott用户分配一个profile要求如下: 1.尝试登录的次数最多4次: 2.如果4次输入错误,则锁定该用户2天: 3.密码每隔5天修改一次,宽限期为2天: 答: SQL>conn sys ...

  7. python多进程并发redis

    Redis支持两种持久化方式RDB和AOF,RDB持久化能够快速的储存和回复数据,但在服务器停机时会丢失大量数据,AOF持久化能够高效的提高数据的安全性,但在储存和恢复数据方面要耗费大量的时间,最好的 ...

  8. python 信号处理

    linux开发中,通常会在进程中设置专门的信号处理方法,比如经常使用的CTRL+C,KILL等信号.如果你熟悉liunx编程,那么python等信号处理方法对你来说就很简单,下面的内容将主要介绍pyt ...

  9. 在Winform混合式框架中整合外部API接口的调用

    在我们常规的业务处理中,一般内部处理的接口多数都是以数据库相关的,基于混合式开发的Winform开发框架,虽然在客户端调用的时候,一般选择也是基于Web API的调用,不过后端我们可能不仅仅是针对我们 ...

  10. 1013团队Beta冲刺day6

    项目进展 李明皇 今天解决的进度 进行前后端联动调试 明天安排 完善程序运行逻辑 林翔 今天解决的进度 服务器端发布消息,删除消息,检索消息,个人发布的action 明天安排 图片功能遇到问题,微信小 ...