A.aspx中
APrincipal user=new Aprincipal();
HttPContext.User=user;
B.aspx中
APrincipal user=(APrincipal )HttPContext.User;
这种写法不对,因为这时候的HttPContext.User是System.Security.Principal.GenericPrincipal类型的,
1、这个GenericPrincipal类型的值的User是什么时候赋值给HttPContext.User的呢,原来HttPContext.User保存的应该是APrincipal 类型的呀?
2、在Application_AuthenticateRequest 事件中可以改写HttPContext.User,
根据Identity.Name,到数据库中做查询,设置APrincipal 的对象User的属性设置,比如权限,角色等。 最后再Context.User=User,这样每次请求页面的时候重新对Context.User赋值,那么和放在页面的Page_Load里面有什么区别呢?为什么还放在Application_AuthenticateRequest 事件里呢?
3、像用户的权限等信息一般存在哪里呢?非得每个页面都到数据库中去读取一次吗?(Application_AuthenticateRequest 事件中处理,实际上也是每次请求都到数据库中读取的),有没有办法存起来呢?登录之后赋值后,其他页面都可以直接用,而不是根据用户ID到数据库中再查询?
因为HTTP是无状态的,你在A里生成了APrinciple对象并且赋值给HttpContext.User了,等你访问B页面的时候,之前的一切结果都消失了,因为你无法保存这个状态。正确的做法是注册一个HttpModule,这个module订阅了HttpContext的AuthenticateRequest事件。在这个事件里,给Context.User去赋值。赋值的凭据就是客户端发过来的cookie,里面有用户登录后生成的凭据(一个加密的token),解析这个token(例如用FormsAuthentication.Decrypt),如果成功,那么就给context.user正确的IPrinciple对象。否则,说明当前用户没有登录(可以给它一个匿名用户对象)。P.S. 客户端包含token的cookie是这样来的:当用户输入用户名密码点登录,服务器端验证通过之后,你给客户端返回一个包含这样token的cookie,这样浏览器下次访问你的站点时,这个cookie就带过来了token,就能把用户信息带过来了。
这种方式,我知道,实际上Identity.Name就是这样解析出来的,然后在根据Identity.Name到数据库中查询,构造IPrinciple对象;这样每次都要对数据库去查询,实际上查询出来的内容,对与同一个用户都是一样发的,能否把根据查询出来的内容构造的IPrinciple对象保存起来,这样其它的地方就不用总去数据库取东西了。不用Session的话,能实现吗?
@hanshuhe: 这样就是服务器端要做好缓存,这类的技术文章很多,你可以搜一下。不过去数据库取一下用户也不是什么很耗性能的事情吧。有的事情是不得不做的。
@水牛刀刀: 如果用缓存来存用户信息(用户对象,包括用户角色,权限等),还不如用session来的方便呢,这样又绕到Session上面了,本来就是想避开Session的。呵呵
@hanshuhe: 这是一个无解的命题,你什么都嫌不好,那就没有任何解决方案可选了。
你可以试试将权限ID神马的按照一定的格式组织成一个字符串然后写入加密票据中,回来的时候解密,解析字符串就可以了。
session啊
就是不想用Session呀,不想用Session+Cookie的方式验证
@hanshuhe: 用属性。
session...
可以看看forms验证 ,肯定是满足你的要求的。
ASP.NET中,你若想保存状态只有使用Session,Application,cookie,viewState这些. 还有一种方法是static的变量,static变量在asp.net中和Application差不多,就不说它了.
保存权限信息,一般的做法是当用户登录的时候,从数据库中获取到用户的权限信息,然后用Session保存之,这样用户访问任意一个页面都可以在服务器端读取权限信息.
楼主想避开session,(虽然不知道楼主为何放弃session这么好的东西).不过办法也有的
1:存在Application中,但要注意存的时候命名可要规定好,不然就被另一用户冲掉了.
user=GetUserInfoFormDB();//获取权限信息
string key="authority_"+user.ID;
Application[key]=user;
Response.Cookies.Add(new HttpCookie("userKey", key));//这里可以对key加密再存到客户端
//这样就可以用户每次请求获取其key,然后再获取其权限信息,不用每次连接数据库.但Application不会自动释放,如果是session,就更简单啦
2:对权限字符串加密,然后存在Cookie中.
3:每个页面都用一个viewState来保存权限信息,这样每次提交都能获得它.而viewState本来就是加密的.
总的来说Application和Session是最好的办法,也是最方便最快捷的办法.
1.可以考虑将数据序列化为json字符串直接放在user的name中.
2.或者使用FormsAuthenticationTicket.
private void SetCooks(string name, string otherData)
{
// 获得Cookie
HttpCookie authCookie = FormsAuthentication.GetAuthCookie(name, false);
// 得到ticket凭据
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(authCookie.Value);
// 根据之前的ticket凭据创建新ticket凭据,然后加入自定义信息
FormsAuthenticationTicket newTicket = new FormsAuthenticationTicket(
ticket.Version, ticket.Name, ticket.IssueDate,
ticket.Expiration, ticket.IsPersistent, otherData);
// 将新的Ticke转变为Cookie值,然后添加到Cookies集合中
authCookie.Value = FormsAuthentication.Encrypt(newTicket);
this.Response.Cookies.Add(authCookie);
}
//使用
var identity = User.Identity as FormsIdentity;
var data = identity.Ticket.UserData;