.net使用IIdentity和IPrincipal实现自定义身份及权限认证【转】

2022-10-15,,,,

1,Webform通过继承BasePage页实现角色权限控制
context.User中保存的信息就是相关的角色与权限信息。Context.User类型为System.Security.Principal.IPrincipal;
Context.User.Identity为System.Security.Principal.IIdentity,因此只要我们实现的上述的两个接口便可实现我们所需的方案
在传统的.NET中,我们可以通过
User.Identity.Name;//获取用户名
User.Identity.IsAuthenticated;//判断用户是否己验证
User.IsInRole("Admin");//判断用户是否含有指定角色
但这样的机制,在实际开发中,难以满足开发需要.我们需要获取更多信息,或者进行更详细的权限判断。
我们可以通过自定义Identity和Principal进行实现!
///<summary>/// 自定义当前用户标识对象
///</summary>publicclass MyIdentity:IIdentity
{
//用户属性(可自定义更多信息)
privatestring _userName;//用户账号privatestring _departmnet;//用户所在部门privatestring _phone;//用户联系电话///<summary>/// 用户账号
///</summary>publicstring UserName
{get { return _userName; } } ///<summary>/// 用户所在部门
///</summary>publicstring Departmnet
{get { return _departmnet; } } ///<summary>/// 用户电话
///</summary>publicstring Phone
{get { return _phone; } } ///<summary>/// 构造函数,根据用户名
///</summary>///<param name="UserName"></param>public MyIdentity(string UserName)
{
//根据UserName查询数据库获得以下数据
    this._userName = "abc";
this._departmnet = "行政部";
this._phone = "";
} ///<summary>/// 构造函数,根据用户ID
///</summary>///<param name="UserID"></param>public MyIdentity(int UserID)
{
//根据UserID查询数据库获得以下数据 this._userName = "abc";
this._departmnet = "行政部";
this._phone = "";
} #region 基本属性
///<summary>/// 返回验证方式
///</summary>publicstring AuthenticationType
{
get { return"Form"; }
} ///<summary>/// 是否验证
///</summary>publicbool IsAuthenticated
{
get { returntrue; }
} ///<summary>/// 返回用户
///</summary>publicstring Name
{
get { return _userName; }
}
#endregion
} ///<summary>/// 当前用户安全上下文信息
///</summary>publicclass MyPrincipal:IPrincipal
{ private IIdentity _identity;//用户标识 private ArrayList _permissionList;//权限列表 ///<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>publicbool IsInRole(string role)
{ returnfalse; } ///<summary>/// 构造函数,用户名构造
///</summary>///<param name="UserName"></param>public MyPrincipal(string UserName)
{
_identity = new MyIdentity(UserName);
//以下权限根据UserName获取数据库用户拥有的权限值,此次省略
_permissionList = new ArrayList();
_permissionList.Add();
_permissionList.Add();
_permissionList.Add();
} ///<summary>/// 构造函数,用户ID构造
///</summary>///<param name="UserID"></param>public MyPrincipal(int UserID)
{
_identity = new MyIdentity(UserID);
//以下权限根据UserName获取数据库用户拥有的权限值,此次省略
_permissionList = new ArrayList();
_permissionList.Add();
_permissionList.Add();
_permissionList.Add();
} ///<summary>/// 判断用户是否拥有某权限
///</summary>///<param name="permissionid"></param>///<returns></returns>publicbool 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>publicclass BasePaper:System.Web.UI.Page
{
public BasePaper()
{ } protectedoverridevoid OnInit(EventArgs e)
{
BasePage_Load();
} ///<summary>/// 设置权限,默认值为0
///</summary>publicvirtualint PermissionID
{ get { return; } } ///<summary>/// 验证方法
///</summary>///<param name="sender"></param>///<param name="e"></param>privatevoid BasePage_Load()
{
//权限检查 bool Permission = true;//初始值为没有权限
//这一步很重要,要代替.NET的自身的User.
HttpContext.Current.User = new ContextUser.MyPrincipal(HttpContext.Current.User.Identity.Name); 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();
}
}
} OK,到了验证页的时候了。
publicpartialclass ascx_Add :BasePage
{
publicoverrideint PermissionID
{
get
{
return;//返回要验证权限值 }
} protectedvoid Page_Load(object sender, EventArgs e)
{ }
} 事实上,在Asp.net MVC模式,更容易对权限进行控制,可以进行更多的细化,对每个动作进行控制。
首先,先实现一个权限验证基类:
///<summary>/// 权限验证基类
/// 2011.7.3
///</summary>publicclass BasePage : AuthorizeAttribute
{
///<summary>/// 权限值
///</summary>privateint _permissionID = ; ///<summary
/// 权限值
///</summary>publicint PermissionID
{
get { return _permissionID; }
set { _permissionID = value; }
} ///<summary>/// 在过程请求授权时调用。
///</summary>///<param name="filterContext">对象包括控制器、HTTP 上下文、请求上下文、操作结果和路由数据。</param>publicoverridevoid 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 != ))
{
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 = )]//返回要验证权限值 public ActionResult Index()
{
// } 无论对Asp.net Form或者Aap.net MVC,都在一个按钮级的权限控制,
那对于,按钮级的权限如何进行控制昵? 看下面代码
//控制删除按扭的显示 <% if((User as account.ContextUser.MyPrincipal).PermissionList.Contains() {%>
<input type="submit" name="button" id="button" value="删除" />
<%} %> 至此,如何实现自定义Identity和Principal,进行整合更多用户信息,和权限验证。
,通过HttpMoudle注册来实现角色权限控制。继承接口和上面一样
创建一个User类实现IIdentity接口 重写相应的方法
publicclass User : IIdentity
{
privateint _id;
privatestring _userName;
privatestring _password;
privatebool _isAuthenticated;
#region properties
publicvirtualint Id
{
get { returnthis._id; }
set { this._id = value; }
}
publicvirtualstring UserName
{
get { returnthis._userName; }
set { this._userName = value; }
}
publicvirtualstring Password
{
get { returnthis._password; }
set { this._password = value; }
}
//是否通过认证publicvirtualbool IsAuthenticated
{
get { returnthis._isAuthenticated; }
set { this._isAuthenticated = value; }
}
//重写为用户IDpublicvirtualstring Name
{
get
{
if (this._isAuthenticated)
returnthis._id.ToString();
elsereturn"";
}
}
publicvirtualstring AuthenticationType
{
get { return"CuyahogaAuthentication"; }
}
public User()
{
this._id = -;
this._isAuthenticated = false;
}
}
创建一个CuyahogaPrincipal类实现IPrincipal接口
publicclass CuyahogaPrincipal : IPrincipal
{
private User _user;
// 返回一个现实IIdentity接口的user对象public IIdentity Identity
{
get { returnthis._user; }
}
// 当前用户是否属于指定角色 在以后的权限认证中可以使用 也可以使用User类中的相关方法来代替publicbool IsInRole(string role)
{
foreach (Role roleObject inthis._user.Roles)
{
if (roleObject.Name.Equals(role))
returntrue;
}
returnfalse;
}
///初始化 若user通过授权则创建public CuyahogaPrincipal(User user)
{
if (user != null && user.IsAuthenticated)
{
this._user = user;
}
else
{
thrownew SecurityException("Cannot create a principal without u valid user");
}
}
}
创建一个实现IHttpModule的AuthenticationModule类
publicclass AuthenticationModule : IHttpModule
{
privateconstint AUTHENTICATION_TIMEOUT = ; public AuthenticationModule()
{
} publicvoid Init(HttpApplication context)
{
context.AuthenticateRequest += new EventHandler(Context_AuthenticateRequest);
} publicvoid Dispose()
{
// Nothing here } //登录时 验证用户时使用publicbool AuthenticateUser(string username, string password, bool persistLogin)
{
//数据访问类
CoreRepository cr = (CoreRepository)HttpContext.Current.Items["CoreRepository"];
string hashedPassword = Encryption.StringToMD5Hash(password);
try
{
//通过用户名密码得到用户对象
User user = cr.GetUserByUsernameAndPassword(username, hashedPassword);
if (user != null)
{
user.IsAuthenticated = true;
//string currentIp = HttpContext.Current.Request.UserHostAddress;
//user.LastLogin = DateTime.Now;
//user.LastIp = currentIp;
// Save login date and IP 记录相关信息 cr.UpdateObject(user);更新用户授权通过信息
// Create the authentication ticket
HttpContext.Current.User = new CuyahogaPrincipal(user); //通过授权 FormsAuthentication.SetAuthCookie(user.Name, persistLogin);
returntrue;
}
else
{
//log.Warn(String.Format("Invalid username-password combination: {0}:{1}.", username, password));returnfalse;
}
}
catch (Exception ex)
{
thrownew Exception(String.Format("Unable to log in user '{0}': " + ex.Message, username), ex);
}
} ///<summary>/// Log out the current user.注销用户
///</summary>publicvoid Logout()
{
if (HttpContext.Current.User != null && HttpContext.Current.User.Identity.IsAuthenticated)
{
FormsAuthentication.SignOut();
}
} privatevoid Context_AuthenticateRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
if (app.Context.User != null && app.Context.User.Identity.IsAuthenticated)//若用户已经通过认证 {
CoreRepository cr = (CoreRepository)HttpContext.Current.Items["CoreRepository"];
int userId = Int32.Parse(app.Context.User.Identity.Name);
User cuyahogaUser = (User)cr.GetObjectById(typeof(User), userId);//得到对应的cuyahogaUser对象
cuyahogaUser.IsAuthenticated = true;
app.Context.User = new CuyahogaPrincipal(cuyahogaUser);//将通过标准窗体认证的user替换成CuyahogaUser, cuyahogaUser包含更多的信息 }
}
}
登录时
protectedvoid btnLogin_Click(object sender, System.EventArgs e)
{
AuthenticationModule am = (AuthenticationModule)Context.ApplicationInstance.Modules["AuthenticationModule"];
if (this.txtUsername.Text.Trim().Length > && this.txtPassword.Text.Trim().Length > )
{
try
{
if (am.AuthenticateUser(this.txtUsername.Text, this.txtPassword.Text, this.chkPersistLogin.Checked))
{
//通过认证 Context.Response.Redirect(Context.Request.RawUrl);
}
else
{
//认证失败 }
}
{
}
}
}
退出登录用
protectedvoid btnLogout_Click(object sender, System.EventArgs e)
{
AuthenticationModule am = (AuthenticationModule)Context.ApplicationInstance.Modules["AuthenticationModule"];
am.Logout();
Context.Response.Redirect(Context.Request.RawUrl);
}
这样就实现了身份认证功能 然后可以方便的实现权限认证
在User类中实现相应的权限逻辑 如: 表示当前用户是否有权限浏览指定的节点
publicbool CanView(Node node)
{
foreach (Permission p in node.NodePermissions)
{
if (p.ViewAllowed && IsInRole(p.Role))
{
returntrue;
}
}
returnfalse;
}
在Page代码中嵌入验证代码即可
User CuyahogaUser = this.User.Identity as User;
if(CuyahogaUser.CanView())
{
}
权限认证模块还是挺简单.
最后在web.config中对AuthenticationModule进行注册

转:https://blog.csdn.net/anihasiyou/article/details/79668267

.net使用IIdentity和IPrincipal实现自定义身份及权限认证【转】的相关教程结束。

《.net使用IIdentity和IPrincipal实现自定义身份及权限认证【转】.doc》

下载本文的Word格式文档,以方便收藏与打印。