首页 新闻 会员 周边 捐助

Context.User保存不住值?

0
悬赏园豆:50 [已解决问题] 解决于 2012-05-21 08:13

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到数据库中再查询?

hanshuhe的主页 hanshuhe | 初学一级 | 园豆:3
提问于:2011-11-14 15:14
< >
分享
最佳答案
0

因为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,就能把用户信息带过来了。

收获园豆:30
水牛刀刀 | 大侠五级 |园豆:6350 | 2011-11-14 15:37

这种方式,我知道,实际上Identity.Name就是这样解析出来的,然后在根据Identity.Name到数据库中查询,构造IPrinciple对象;这样每次都要对数据库去查询,实际上查询出来的内容,对与同一个用户都是一样发的,能否把根据查询出来的内容构造的IPrinciple对象保存起来,这样其它的地方就不用总去数据库取东西了。不用Session的话,能实现吗?

hanshuhe | 园豆:3 (初学一级) | 2011-11-14 18:05

@hanshuhe: 这样就是服务器端要做好缓存,这类的技术文章很多,你可以搜一下。不过去数据库取一下用户也不是什么很耗性能的事情吧。有的事情是不得不做的。

水牛刀刀 | 园豆:6350 (大侠五级) | 2011-11-14 18:14

@水牛刀刀: 如果用缓存来存用户信息(用户对象,包括用户角色,权限等),还不如用session来的方便呢,这样又绕到Session上面了,本来就是想避开Session的。呵呵

hanshuhe | 园豆:3 (初学一级) | 2011-11-14 20:00

@hanshuhe: 这是一个无解的命题,你什么都嫌不好,那就没有任何解决方案可选了。

水牛刀刀 | 园豆:6350 (大侠五级) | 2011-11-15 00:38

你可以试试将权限ID神马的按照一定的格式组织成一个字符串然后写入加密票据中,回来的时候解密,解析字符串就可以了。

邹华栋 | 园豆:209 (菜鸟二级) | 2011-12-26 22:31
其他回答(5)
0

session啊

悟行 | 园豆:12559 (专家六级) | 2011-11-14 15:19

就是不想用Session呀,不想用Session+Cookie的方式验证

 

支持(0) 反对(0) hanshuhe | 园豆:3 (初学一级) | 2011-11-14 18:00

@hanshuhe: 用属性。

支持(0) 反对(0) 悟行 | 园豆:12559 (专家六级) | 2011-11-14 18:07
0

session...

[CC] | 园豆:61 (初学一级) | 2011-11-15 08:23
0

可以看看forms验证 ,肯定是满足你的要求的。

chenping2008 | 园豆:9836 (大侠五级) | 2011-11-17 09:37
0

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是最好的办法,也是最方便最快捷的办法.

 

 

 

 

收获园豆:10
coder_wang | 园豆:193 (初学一级) | 2011-11-17 15:51
1

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;
收获园豆:10
zhangweiwen | 园豆:904 (小虾三级) | 2011-11-17 18:12
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册