在做一个分目录验证的后台程序。
根目录设置为任何人都能访问,下设二个二级目录admin,member.
登陆页在admin目录下,admin/login.aspx(该页面在根目录web.config文件里设置为任何人可访问).当登陆成功后,跳转到admin/index.aspx页面(该页面是有frameset框架组成的,二栏二列。),当跳转过来的时候就出现问题了,三个框架页都自动跳转到没有通过验证的error.aspx。而显示没有通过验证,我测试过cookie中的user的信息是有的,roles也有,但是却不在我赋的那个roles值中.这个问题很郁闷啊,我把代码贴出来,希望大家能帮我解决这个“心结”。
根目录web.config关键代码片段:
<authentication mode="Forms">
          <forms loginUrl="error.aspx" timeout="30" path="/" name=".yzone" protection="All"/>
          </authentication>
<authorization>
        <allow users="*"/>
        </authorization>
    </system.web><location path="admin">
 <system.web>
    <authorization>
      <allow roles="admin,kf"/>
      <deny users="*"/>
    </authorization>
    </system.web>
  <location path="admin/login.aspx">
    <system.web>
      <authorization>
        <allow users="*"/>
        </authorization>
      </system.web>
  </location>
</configuration>
以下是admin/login.aspx的代码片段:
string cmdtext = "select roles from mb_user where username='"+user+"' and password='"+md5.Encrypt(pass)+"'";
        SqlDataReader dr = cn.dr(cmdtext);
        if (dr.Read())
        {
            FormsAuthenticationTicket Ticket = new FormsAuthenticationTicket(1,user.ToString(),DateTime.Now,DateTime.Now.AddMinutes(30),false,dr["roles"].ToString());
            string hashTicket = FormsAuthentication.Encrypt(Ticket);
            HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName,hashTicket);
            cookie.Expires = DateTime.Now.AddMinutes(30);
            Response.Cookies.Add(cookie);
            Server.Transfer("index.aspx");
        }
        else
        {
            Response.Write("<script>alert(\"用户名或密码错误\");location.href='login.aspx';</script>"); 
        }
        dr.Close();
        Response.End();
以下是admin/index.aspx的代码片段:
<frameset border="0" name="body_1" frameSpacing="0" frameBorder="0" marginwidth="0" marginheight="0" leftmargin="0" topmargin="0" rows="50,*">
   <frame border="0" name="top" borderColor="#6699cc" marginWidth="0" marginHeight="0" frameBorder="0" scrolling="no" LEFTMARGIN="0" TOPMARGIN="0" target="left" src="top.aspx">
   <frameset border="0" name="body_2" frameSpacing="0" frameBorder="1" marginwidth="0" marginheight="0" leftmargin="0" topmargin="0" cols="180,*">
        <frame border="0" name="left" borderColor="#6699cc" marginWidth="0" marginHeight="0" frameBorder="0" scrolling="yes" LEFTMARGIN="0" TOPMARGIN="0" target="main" src="left.aspx">
        <frame border="0" name="main" borderColor="#6699cc" marginWidth="0" marginHeight="0" frameBorder="0" scrolling="auto" LEFTMARGIN="0" TOPMARGIN="0" src="main.aspx">
   </frameset>
</frameset>

解决方案 »

  1.   

    我刚再次测试了,FORMS验证成功后,User.IsInRole("admin")为false.很奇怪!在生成验证票的时候代码都没有错误的啊!
      

  2.   

            void app_EndRequest(object sender, EventArgs e)
            {
                foreach (string key in HttpContext.Current.Response.Cookies)
                {
                    HttpContext.Current.Response.Cookies[key].Domain = ConfigurationManager.AppSettings["domain"];
                }
    加入这个,以后就方便了。这个代码目的是:把所有发送给客户端的cookie的域名都设置为顶级域名。
    这样所有二级域名都可以获取到了。而且在EndRequest里做这个工作,一劳永逸!以后都不需要担心cookie读取不到
      

  3.   

    小灰,我在登陆页测试了,过程是这样的,登陆成功后,FORMS验证代码也执行过了,就在登陆页输出user和roles,只能输出user,User.IsInRole("admin")为false.
      

  4.   

    不想看你代码了,我这里有个通用的:恢复角色、身份代码:private void app_AuthenticateRequest(object sender, EventArgs e)
            {
                // 提取窗体身份验证 cookie
                string cookieName = FormsAuthentication.FormsCookieName;
                HttpCookie authCookie = HttpContext.Current.Request.Cookies[cookieName];            if (null == authCookie)
                {
                    // 没有身份验证 cookie。
                    return;
                }            FormsAuthenticationTicket authTicket = null;
                authTicket = FormsAuthentication.Decrypt(authCookie.Value);            if (null == authTicket)
                {
                    // 无法解密 Cookie。
                    return;
                }
                // 创建票证后,为 UserData 属性指定一个
                // 以管道符分隔的角色名字符串。
                string[] roles = authTicket.UserData.Split(new char[] { ',' });
                // 创建一个标识对象
                FormsIdentity id = new FormsIdentity(authTicket);            // 该主体将通过整个请求。
                GenericPrincipal principal = new GenericPrincipal(id, roles);
                // 将新的主体对象附加到当前的 HttpContext 对象
                HttpContext.Current.User = principal;
            }登录注销代码:public static void Login(string username, string roles, bool isPersistent)
            {
                DateTime dt = isPersistent ? DateTime.Now.AddMinutes(99999) : DateTime.Now.AddMinutes(60);
                FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
                                                                                    1, // 票据版本号
                                                                                    username, // 票据持有者
                                                                                    DateTime.Now, //分配票据的时间
                                                                                    dt, // 失效时间
                                                                                    isPersistent, // 需要用户的 cookie 
                                                                                    roles, // 用户数据,这里其实就是用户的角色
                                                                                    FormsAuthentication.FormsCookiePath);//cookie有效路径            //使用机器码machine key加密cookie,为了安全传送
                string hash = FormsAuthentication.Encrypt(ticket);
                HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash); //加密之后的cookie            //将cookie的失效时间设置为和票据tikets的失效时间一致 
                HttpCookie u_cookie = new HttpCookie("username", username);
                if (ticket.IsPersistent)
                {
                    u_cookie.Expires = ticket.Expiration;
                    cookie.Expires = ticket.Expiration;
                }            //添加cookie到页面请求响应中
                HttpContext.Current.Response.Cookies.Add(cookie);
                HttpContext.Current.Response.Cookies.Add(u_cookie);
            }        public static void Logout()
            {
                HttpCookie cookie = HttpContext.Current.Response.Cookies[FormsAuthentication.FormsCookieName];            if (cookie == null)
                {
                    cookie = new HttpCookie(FormsAuthentication.FormsCookieName);
                    HttpContext.Current.Response.Cookies.Add(cookie);
                }
                cookie.Expires = DateTime.Now.AddYears(-10);            HttpCookie u_cookie = new HttpCookie("username", string.Empty);
                u_cookie.Expires = DateTime.Now.AddYears(-10);
                HttpContext.Current.Response.Cookies.Add(u_cookie);
            }web.config里设置:
    <authentication mode="Forms">
    </authentication>
      

  5.   

    不好意思,我看到了
     bool isPersistent
      

  6.   

    测试小灰的代码后,是正确的,但我这边还是无法找到指定的roles。
      

  7.   

    我知道哈,我只测试了一个roles和一个user
    user:yzone
    roles:china
    验证过后yzone可以输出
    但生成cookie中roles没有在china这个roles中.
      

  8.   

    问题解决了吗?我也碰到了你类似的问题,在app_AuthenticateRequest里测试isinrole()是true,但是跳到default之后值就是false,但是能得到请求用户的identity.name属性