先说一句:师姐把框架搭起来后。每个后台只要简单的加上对应的引用。就可以自动实现权限判断。不需要再去修改源程序。
另外:师姐忙毕业的事情,已经不再带我了。而我还是个菜鸟。请各位多多指教。
认证和授权误入迷途
我原本想。
Security.UserPrincipal newUser = Security.UserPrincipal.ValidateLogin(userName, password);
//把生成的用户对象放入Context.User,这样做将会把完整的用户信息加载到ASP.NET提供的验证体系中
Context.User = newUser;
FormsAuthentication.SetAuthCookie(userName, false);
这样只能保证 其他页面中Context.User能取出用户名来。其他的根本没有用了。只是做一次密码验证和角色验证吗?
一直在困惑。现在才明白。又进入牛角尖了。师姐说过:你一直在用一个没解决的方法去解决问题。应该换个角度。
这次我不再跟踪代码。
我利用URL直接进入其他页面。发现根本没有进入PAGE_LOAD里面的具体操作就直接返回一个“没有权限”了。
于是,才想到,师姐一直说“基页”“基页”的方式。
然后再找到真正的破解方式.
师姐谈过的 认证和授权的使用方式如下
1. 让所有的页面都继承自基页。
namespace Web.Opanel.UpdatePassword
{
public partial class UpdatePassword : Security.BasePage
{
让所有的页面都继承自基页。
2.这里利用了三个类来做的权限
BasePage.cs//基页 功能:继承此基页的WEB页面加载之前用此基页的方法 来做权限验证操作;引用//UserPrincipal.cs的对象实例来进行权限操作和读取判断。
UserPrincipal.cs(授权)//基页中使用,功能:根据用户名(验证用户名)来得到 权限,角色。并引 //用UserIdentity.cs创建其对象实例来得到验证信息
UserIdentity.cs(验证)//得到用户名,进行验证,并标注是否验证、验证密码。
这里引出一个问题。
BasePage中对具体权限和验证的方法所需要的对象是从哪里读取的问题?
读取有两种方式:SESSION 和 Context.User
而对于的,这两种方式都要求在登录的后台中 进行存入。
如果使用Session存储用户信息。
(登录时)
Session["UserInfo"] = currentUser;//把对象信息放入session中
(BasePage中)
if ((Session["UserInfo"] == null))
{
FormsAuthentication.SignOut();
Session.Clear();
Session.Abandon();
Response.Clear();
Response.Write("<script defer>window.alert('您没有权限进入本页或当前登录用户已过期!\\n请重新登录或与管理员联系!');parent.location='" + Common.ServerInfo.GetRootURI() + "Login/Login.aspx';</script>");
Response.End();
}
如果使用Context.User存储信息。
这里牵扯到一个FORM验证
(登录时)
FormsAuthentication.SetAuthCookie(userName, false);
单独只写一个FORM验证。使用Context.User.Identity.Name就可以得到数据。
因为。CONTEXT是HTTP.CONTEXT。Context.User.Identity是.NET中System.Security.Principal.Iprincipal. IIdentity Identity不是你自己定义的Identity对象。
(BasePage)if (!Context.User.Identity.IsAuthenticated)
{
FormsAuthentication.SignOut();
Session.Clear();
Session.Abandon();
Response.Clear();
Response.Write("<script defer>window.alert('您没有权限进入本页或当前登录用户已过期!\\n请重新登录或与管理员联系!');parent.location='" + Common.ServerInfo.GetRootURI() + "/Opanel/Login/Login.aspx';</script>");
Response.End();
}
当然。这里并不是说SESSION用了。FormsAuthentication验证就不能用了。你完全可以同时用这两种方式来结合进行存储。但FORM验证中有时间限制,这里建议用SESSION存储(也有时间限制)。因为Session存储的比较多(MODEL)。FORM验证也可以存大量数据。必须自己去重写:参考:http://www.tracefact.net/Asp-Net/FormsAuthentication.aspx
上面只是比较简单的一种验证和角色
————————————————
下面有一个针对每个角色以及其增删改查权限的设计。
使用时:
OperationType operationType = (OperationType)Enum.Parse(typeof(OperationType), Request["operationType"].ToString());//操作类型
Command.AdminInfo.Receiver receiver = new Command.AdminInfo.User(Context.User.Identity.Name.ToString(), operationType.GetHashCode().ToString());
----第一句
『public User(string _username, int _PermissionID)
{
this.username = _username;//用户名
this.PermissionID = _PermissionID;//权限的CODE
//this.operationType = _PermissionID;
}
public User(string _username, string _operationType)
{
this.username = _username;
this.operationType = _operationType;
queryOperation = QueryOperation();
addOperation = AddOperation();
deleteOperation = DeleteOperation();
updateOperation = UpdateOperation();
}
』
Command.AdminInfo.Command command = new Command.AdminInfo.Operation(receiver);
『此方法里有一个public override void execute()
{
this.receiver.Operation();//其实就是USER中的方法,验证是否有权限
//throw new NotImplementedException();
}』
Command.AdminInfo.Invoker invoker = new Command.AdminInfo.Invoker();
『private List<Command> command=new List<Command>();
public void setCommand(Command _command)
{
//this.command = _command;
command.Add(_command);//多个权限的《receiver》LIST集合。(每个权限都是一个对象)
}
public void action()
{
foreach (Command cmd in command)
{
cmd.execute();//执行USER的执行 遍历判断是否有权限
}
//this.command.execute();
}』
invoker.setCommand(command);//把最新的操作放进去
invoker.action();//执行。
如果在你操作时。USER判定你没有此操作权限则
『
if (!TestOperation())
{
string st = string.Empty;
st = "{result:'您没有权限执行此操作!'}";
HttpContext.Current.Response.Write(st);
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.End();//当前的输出将被打断。即其他的程序也不会再进行了。
}
v』
所以。只要把以上这些代码放入 PAGE——LoaD 中的最开头就可以了。不需要担心下面的方法是否执行。
要注意:使用此的类时。如果不是增删改查的话。就会被默认为有权限
『/// </summary>
protected bool TestOperation()
{
bool OPermission = true;
switch (operationType)
{
case "1"://查询权限
if (queryOperation == "0")
{
OPermission = false;
}
break;
case "2"://插入权限
if (addOperation == "0")
{
OPermission = false;
}
break;
case "3"://删除权限
if (deleteOperation == "0")
{
OPermission = false;
}
break;
case "4"://修改权限
if (updateOperation == "0")
{
OPermission = false;
}
break;
default:
break;
}
return OPermission;
}』
学习经历:
- 对不钻牛角的学习方式 感觉豁然开朗
- 对于微软.NET中的接口终于有了认识。就像:.Iprincipal. Iidentity这些接口。其实他们只是借口。重要的是。我们继承接口进行我们想要的开发。
- 要多看,多想才能明白
- 为什么我们对.NET或JAVA内部的类不认识。因为我们看不到其中的代码怎么写的。只是硬性的记忆它的功能,而不知道,它内部怎么执行的。就好象以上中,为什么必须放在头部?为什么其他类型就可以( HttpContext.Current.Response.End();和默认初始 为 TRUE。只有没有增删改查这四个权限时才为FALSE.其他权限的默认为TRUE)
- 这里师姐写这个工厂模式的类,让我感觉很有点站在架构上写代码的感觉了。
向师姐学习。因为看这样的代码是一种享受。加油。设计框架的时候,面向对象的思想才得到真正的体现。例如,接口,继承,多态。以前只是知道。现在看完师姐的框架终于明白他们为什么要出现。为什么有的程序员牛。有的不行。加油。
还有各位不要向上次那么无聊,多讨论技术。欢迎大家交流、指教。我是一个成长中的菜鸟。