一、前言
关于表单验证,园子里已经有不少的文章,相信Web开发人员也都基本写过,最近在一个个人项目中刚好用到,在这里与大家分享一下。本来想从用户注册开始写起,但发现东西比较多,涉及到界面、前端验证、前端加密、后台解密、用户密码Hash、权限验证等等,文章写起来可能会很长,所以这里主要介绍的是登录验证和权限控制部分,有兴趣的朋友欢迎一起交流。
一般验证方式有Windows验证和表单验证,web项目用得更多的是表单验证。原理很简单,简单地说就是利用浏览器的cookie,将验证令牌存储在客户端浏览器上,cookie每次会随请求发送到服务器,服务器验证这个令牌。通常一个系统的用户会分为多种角色:匿名用户、普通用户和管理员;这里面又可以再细分,例如用户可以是普通用户或Vip用户,管理员可以是普通管理员或超级管理员等。在项目中,我们有的页面可能只允许管理员查看,有的只允许登录用户查看,这就是角色区分(Roles);某些特别情况下,有些页面可能只允许叫“张三”名字的人查看,这就是用户区分(Users)。
我们先看一下最后要实现的效果:
1.这是在Action级别的控制。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | public class Home1Controller : Controller {
//匿名访问
public ActionResult Index()
{
return View();
}
//登录用户访问
[RequestAuthorize]
public ActionResult Index2()
{
return View();
}
//登录用户,张三才能访问
[RequestAuthorize(Users= "张三" )]
public ActionResult Index3()
{
return View();
}
//管理员访问
[RequestAuthorize(Roles= "Admin" )]
public ActionResult Index4()
{
return View();
} } |
2.这是在Controller级别的控制。当然,如果某个Action需要匿名访问,也是允许的,因为控制级别上,Action优先级大于Controller。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | //Controller级别的权限控制 [RequestAuthorize(User= "张三" )] public class Home2Controller : Controller {
//登录用户访问
public ActionResult Index()
{
return View();
}
//允许匿名访问
[AllowAnonymous]
public ActionResult Index2()
{
return View();
} } |
3.Area级别的控制。有时候我们会把一些模块做成分区,当然这里也可以在Area的Controller和Action进行标记。
从上面可以看到,我们需要在各个地方进行标记权限,如果把Roles和Users硬写在程序中,不是很好的做法。我希望能更简单一点,在配置文件进行说明。例如如下配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <? xml version="1.0" encoding="utf-8" ?> <!--
1.这里可以把权限控制转移到配置文件,这样就不用在程序中写roles和users了
2.如果程序也写了,那么将覆盖配置文件的。
3.action级别的优先级 > controller级别 > Area级别 --> < root >
<!--area级别-->
< area name="Admin">
< roles >Admin</ roles >
</ area >
<!--controller级别-->
< controller name="Home2">
< user >张三</ user >
</ controller >
<!--action级别-->
< controller name="Home1">
< action name="Inde3">
< users >张三</ users >
</ action >
< action name="Index4">
< roles >Admin</ roles >
</ action >
</ controller > </ root > |
写在配置文件里,是为了方便管理,如果程序里也写了,将覆盖配置文件的。ok,下面进入正题。
二、主要接口
先看两个主要用到的接口。
IPrincipal定义了用户对象的基本功能,接口定义如下:
1 2 3 4 5 6 7 | public interface IPrincipal {
//标识对象
IIdentity Identity { get ; }
//判断当前角色是否属于指定的角色
bool IsInRole( string role); } |
它有两个主要成员,IsInRole用于判断当前对象是否属于指定角色的,IIdentity定义了标识对象信息。HttpContext的User属性就是IPrincipal类型的。
IIdentity定义了标识对象的基本功能,接口定义如下:
1 2 3 4 5 6 7 8 9 | public interface IIdentity {
//身份验证类型
string AuthenticationType { get ; }
//是否验证通过
bool IsAuthenticated { get ; }
//用户名
string Name { get ; } } |
IIdentity包含了一些用户信息,但有时候我们需要存储更多信息,例如用户ID、用户角色等,这些信息会被序列到cookie中加密保存,验证通过时可以解码再反序列化获得,状态得以保存。例如定义一个UserData。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public class UserData : IUserData {
public long UserID { get ; set ; }
public string UserName { get ; set ; }
public string UserRole { get ; set ; }
public bool IsInRole( string role)
{
if ( string .IsNullOrEmpty(role))
{
return true ;
}
return role.Split( ‘,‘ ).Any(item => item.Equals( this .UserRole, StringComparison.OrdinalIgnoreCase));
}
public bool IsInUser( string user)
{
if ( string .IsNullOrEmpty(user))
{
return true ;
}
return user.Split( ‘,‘ ).Any(item => item.Equals( this .UserName, StringComparison.OrdinalIgnoreCase));
} } |
UserData实现了IUserData接口,该接口定义了两个方法:IsInRole和IsInUser,分别用于判断当前用户角色和用户名是否符合要求。该接口定义如下:
1 2 3 4 5 | public interface IUserData {
bool IsInRole( string role);
bool IsInUser( string user); } |
接下来定义一个Principal实现IPrincipal接口,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public class Principal : IPrincipal {
public IIdentity Identity{ get ; private set ;}
public IUserData UserData{ get ; set ;}
知识推荐
我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8
不良信息举报平台
互联网安全管理备案
Copyright 2023 www.wodecom.cn All Rights Reserved |