.NET 实现自定义ContextUser的Identity和Principal实现自定义用户信息,权限验证。出手必精!

MSDNXGH 2011-10-21 07:13:52
加精

在传统的.NET中,我们可以通过


User.Identity.Name;//获取用户名
User.Identity.IsAuthenticated;//判断用户是否己验证
User.IsInRole("Admin");//判断用户是否含有指定角色


但这样的机制,在实际开发中,难以满足开发需要.仅仅通过User.Identity.Name;获取用户名,和User.Identity.IsAuthenticated;判断用户是否验证,是难以满足需要。如何获取用户更多信息,或者进行更详细的权限判断。

我们可以通过自定义Identity和Principal进行实现!


/// <summary>
/// 自定义当前用户标识对象
/// </summary>
public class MyIdentity:IIdentity
{

#region 用户属性(可自定义更多信息)
private string _userName;//用户账号
private string _departmnet;//用户所在部门
private string _phone;//用户联系电话
#endregion

/// <summary>
/// 用户账号
/// </summary>
public string UserName
{
get { return _userName; }
}
/// <summary>
/// 用户所在部门
/// </summary>
public string Departmnet
{
get { return _departmnet; }
}
/// <summary>
/// 用户电话
/// </summary>
public string Phone
{
get { return _phone; }
}
/// <summary>
/// 构造函数,根据用户名
/// </summary>
/// <param name="UserName"></param>
public MyIdentity(string UserName)
{
//根据UserName查询数据库获得以下数据
this._userName = "abc";
this._departmnet = "行政部";
this._phone = "123456";
}
/// <summary>
/// 构造函数,根据用户ID
/// </summary>
/// <param name="UserID"></param>
public MyIdentity(int UserID)
{
//根据UserName查询数据库获得以下数据
this._userName = "abc";
this._departmnet = "行政部";
this._phone = "123456";
}
#region 基本属性
/// <summary>
/// 返回验证方式
/// </summary>
public string AuthenticationType
{
get { return "Form"; }
}
/// <summary>
/// 是否验证
/// </summary>
public bool IsAuthenticated
{
get { return true; }
}
/// <summary>
/// 返回用户
/// </summary>
public string Name
{
get { return _userName; }
}
#endregion
}



/// <summary>
/// 当前用户安全上下文信息
/// </summary>
public class MyPrincipal:IPrincipal
{
#region 属性
private IIdentity _identity;//用户标识
private ArrayList _permissionList;//权限列表
#endregion

/// <summary>
/// 返回用户权限列表
/// </summary>
public ArrayList PermissionList
{
get { return _permissionList; }
}

/// <summary>
/// 获取当前用户标识
/// </summary>
public IIdentity Identity
{
get { return _identity; }
}
/// <summary>
/// 当前用户是否指定角色(采用权限值方式,此处返回false)
/// </summary>
/// <param name="role"></param>
/// <returns></returns>
public bool IsInRole(string role)
{
return false;//返回false
}
/// <summary>
/// 构造函数,用户名构造
/// </summary>
/// <param name="UserName"></param>
public MyPrincipal(string UserName)
{
_identity = new MyIdentity(UserName);
//以下权限根据UserName获取数据库用户拥有的权限值,此次省略
_permissionList = new ArrayList();
_permissionList.Add(1);
_permissionList.Add(2);
_permissionList.Add(3);
_permissionList.Add(4);
_permissionList.Add(5);
}
/// <summary>
/// 构造函数,用户ID构造
/// </summary>
/// <param name="UserID"></param>
public MyPrincipal(int UserID)
{
_identity = new MyIdentity(UserID);
//以下权限根据UserName获取数据库用户拥有的权限值,此次省略
_permissionList = new ArrayList();
_permissionList.Add(1);
_permissionList.Add(2);
_permissionList.Add(3);
_permissionList.Add(4);
_permissionList.Add(5);
}
/// <summary>
/// 判断用户是否拥有某权限
/// </summary>
/// <param name="permissionid"></param>
/// <returns></returns>
public bool IsPermissionID(int permissionid)
{
return _permissionList.Contains(permissionid);
}
}


好,上面我们己实现了自定义,Identity和Principal。

我们可以在页面这样使用Identity。


//页面中输出自定义用户信息
<%=(User.Identity as ContextUser.MyIdentity).Name %>//用户账号
<%=(User.Identity as ContextUser.MyIdentity).Phone %>//用户电话
<%=(User.Identity as ContextUser.MyIdentity).Departmnet %>//用户所在部门


自定义显示用户信息后,我们接着利用Principal进行权限验证和控制

在Asp.net Web模式下,使用方式:

首先,我们先做一个权限验证基类!

/// <summary>
///权限验证基类
/// </summary>
public class BasePaper:System.Web.UI.Page
{
public BasePaper()
{
//
//TODO: 在此处添加构造函数逻辑
//
}
protected override void OnInit(EventArgs e)
{
BasePage_Load();
}
/// <summary>
/// 设置权限,默认值为0
/// </summary>
public virtual int PermissionID
{
get { return 0; }
}
/// <summary>
/// 验证方法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BasePage_Load()
{
//权限检查
#region 权限检查
bool Permission = true;//初始值为没有权限

//这一步很重要,要代替.NET的自身的User.
ContextUser.MyPrincipal MyPrincipal = new ContextUser.MyPrincipal(HttpContext.Current.User.Identity.Name);
HttpContext.Current.User = MyPrincipal;

if ((User as account.ContextUser.MyPrincipal).PermissionList.Contains(PermissionID))
{
Permission = false;//验证通过
}
if (Permission)//权限验证不通过
{
Response.Clear();
Response.Write("<script language=\"javascript\">alert(\"对不起,你没有权限进入\");history.go(-1);</script>");
Response.End();
}
#endregion
}
}


OK,到了验证页的时候了。


public partial class ascx_Add :BasePage
{
public override int PermissionID
{
get
{
return 13;//返回要验证权限值
}
}
protected void Page_Load(object sender, EventArgs e)
{
//
}
}


事实上,在Asp.net MVC模式,更容易对权限进行控制,可以进行更多的细化,对每个动作进行控制。

MVC模式下:

首先,先实现一个权限验证基类:


/// <summary>
/// 权限验证基类
/// 2011.7.3
/// </summary>
public class BasePage : AuthorizeAttribute
{
/// <summary>
/// 权限值
/// </summary>
private int _permissionID = 0;
/// <summary
/// 权限值
/// </summary>
public int PermissionID
{
get { return _permissionID; }
set { _permissionID = value; }
}
/// <summary>
/// 在过程请求授权时调用。
/// </summary>
/// <param name="filterContext">对象包括控制器、HTTP 上下文、请求上下文、操作结果和路由数据。</param>
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
//这一步很重要,要代替.NET的自身的User.
ContextUser.MyPrincipal MyPrincipal = new ContextUser.MyPrincipal(HttpContext.Current.User.Identity.Name);
HttpContext.Current.User = MyPrincipal;

if ((!MyPrincipal.ISPermissionID(_permissionID)) && (_permissionID != 0))
{
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.Write("<script defer>window.alert('无权操作!');history.back();</script>");
HttpContext.Current.Response.End();
filterContext.Result = new EmptyResult();
}
}
else
{
FormsAuthentication.SignOut();
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.Write("<script defer>window.alert('无权操作!或当前登录用户已过期!\\n请重新登录或与管理员联系!');</script>");
HttpContext.Current.Response.End();
filterContext.Result = new EmptyResult();
}
}

}


回到控制器,进行权限验证


[BasePage(PermissionID = 13)]//返回要验证权限值
public ActionResult Index()
{
//
}


无论对Asp.net Form或者Aap.net MVC,都在一个按钮级的权限控制,
那对于,按钮级的权限如何进行控制昵?

看下面代码


//控制删除按扭的显示
<% if((User as account.ContextUser.MyPrincipal).PermissionList.Contains(13) {%>
<input type="submit" name="button" id="button" value="删除" />
<%} %>


至此,如何实现自定义Identity和Principal,进行整合更多用户信息,和权限验证。己经介绍完了。

更多问题,请大家加入.NET技术群进行讨论.群号是:160046333,欢迎加入。管理员勿删此信息。
...全文
3026 113 打赏 收藏 转发到动态 举报
写回复
用AI写文章
113 条回复
切换为时间正序
请发表友善的回复…
发表回复
mloo 2013-01-04
  • 打赏
  • 举报
回复
新手,看看就好,先mark
sharp_scr 2011-10-27
  • 打赏
  • 举报
回复
最近刚好也在折腾这个东西 弱弱的问下 你的验证基类里面ArrayList _permissionList实际也是通过读取数据库 然后根据UserID筛选出来的吧(即根据每个登陆用户的角色获得其权限列表) 然后再做权限判断(页面级、菜单级) 那系统每个页面都继承这个验证基类 载入页面时会不会造成并发数的问题? 不知道想的对不对 如果有问题 别拍砖啊 哈哈~
Name_456 2011-10-27
  • 打赏
  • 举报
回复
谢谢,学习了
mame73 2011-10-26
  • 打赏
  • 举报
回复
学习了, 不过太复杂
myth_sky 2011-10-26
  • 打赏
  • 举报
回复
留名,,学习下·|~~~
诚朴勇毅 2011-10-26
  • 打赏
  • 举报
回复
收藏了
yanfeidezh 2011-10-26
  • 打赏
  • 举报
回复
都好强悍!
yehua7 2011-10-26
  • 打赏
  • 举报
回复
谢谢,学习了
liujf 2011-10-26
  • 打赏
  • 举报
回复
学习了,感谢 分享
lanbingdao 2011-10-26
  • 打赏
  • 举报
回复
谢谢,很有参考价值
liyf_liyunfeng 2011-10-26
  • 打赏
  • 举报
回复
来学习,顶一下。
seacen 2011-10-26
  • 打赏
  • 举报
回复
学习了下,谢谢分享
沙鸥 2011-10-26
  • 打赏
  • 举报
回复
谢谢分享,学习了!!!
Soultack 2011-10-26
  • 打赏
  • 举报
回复
来学习了。。。呵呵
DigitalMonk 2011-10-26
  • 打赏
  • 举报
回复
学习!
swanmsg 2011-10-26
  • 打赏
  • 举报
回复
不知楼主是撰写博文,还是宣传自己的独到之处?
computer_li 2011-10-26
  • 打赏
  • 举报
回复
[Quote=引用 66 楼 a157147899 的回复:]

看了一下验证方式比较繁琐。
如果一个ERP系统 有1000个页面
每个页面的都要去继承一下你的BasePage
同时每个页面还需要定义页面权限标识,会给维护造成一定影响。
C# code

public override int PermissionID
{
get
{
return 13;//返回要验证权限值
……
[/Quote]
动作跟踪怎么处理?
test0 2011-10-26
  • 打赏
  • 举报
回复
学习,谢谢
低调的感觉 2011-10-25
  • 打赏
  • 举报
回复
黄亮 2011-10-25
  • 打赏
  • 举报
回复
收藏,收藏
加载更多回复(71)

62,074

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧