FineUI 官方论坛

标题: 如何避免用户绕开tree,直接敲地址进子页面 [打印本页]

作者: 898806387    时间: 2017-6-30 16:55
标题: 如何避免用户绕开tree,直接敲地址进子页面
我想,点击树节点的时候,先往cookie写个值,
子页面判断页面名称是否与cookie一致,
这样可以避免用户直接敲页面地址,打开子页面

但发现 好像tree.Node.NavigateUrl 优先于 tree.NodeCommand 执行

这样导致cookie里没有值

请教各位大神有什么其他的方法可以实现这个想法?


作者: 898806387    时间: 2017-6-30 16:56
哦,补充一下
tree是根据权限动态生成的,只显示有权限的树节点
作者: 898806387    时间: 2017-6-30 17:16
--------------------------PageHelper.cs-------------------------------------------

using System.Linq;
using System.Web;
using System.Data;
using FineUI;
using System.Web.UI;

public class PageHelper
{
    public static bool Check_page(Page p)
    {
        //HttpSessionState Session = HttpContext.Current.Session;

        target = HttpContext.Current.Request.Cookies["target"].Value;
        string target1 = p.Request.CurrentExecutionFilePath;

        bool isAuthed = false;
        if ("/"+target == target1)
        {
            isAuthed = true;
        }
        return isAuthed;
    }



    //左侧树形权限菜单用
    private static DataTable DtTree;
   
    private static string uid;
    private static string target;

    private static void init_uid()
    {
        HttpRequest Request = HttpContext.Current.Request;
        uid = Request.Cookies["uid"].Value;

    }

    public static void Init_Auth(Tree TV, string P_ID, bool isNav)
    {
        init_uid();
        string connString = OraData.strConnection;
        string SQL1 = "SELECT DISTINCT A.P_ID,A.ID,A.NAME,A.TARGET,A.AUTH,A.VISIBLE,A.ICON,A.SORT FROM WEB_LEFT_TREE A LEFT JOIN WEB_ROLE_MENU B ON A.ID = B.R_MENU LEFT JOIN WEB_USER_ROLE C ON B.R_ID = C.U_ROLE  LEFT JOIN WEB_USER_MENU D ON A.ID = D.U_MENU ";
        SQL1 = SQL1 + "WHERE(A.AUTH = 0 OR C.U_ID = '" + uid + "' OR D.U_ID = '" + uid + "') AND A.VISIBLE = 1 ORDER BY A.ID,A.SORT ";
        DtTree = OraData.ExecuteDataTable(connString, CommandType.Text, SQL1, null);
        DataRow[] dr;
        if (P_ID == "")
        {
            dr = DtTree.Select("P_ID IS NULL");
        }
        else

        {
            dr = DtTree.Select("P_ID =" + P_ID + "");
        }

        if (dr.Count() > 0)
        {
            TV.Nodes.Clear();
            for (int i = 0; i < dr.Count(); i++)
            {
                TreeNode TNT = new TreeNode();
               
                TNT.Text = dr["NAME"].ToString();
                TNT.NodeID = dr["ID"].ToString();
                string IconPath = "~/extjs/res/icon/";
                if (dr["ICON"].ToString() == "")
                {
                    IconPath = IconPath + "folder" + ".png";
                }
                else
                {
                    IconPath = IconPath + dr["ICON"].ToString() + ".png";
                }
                TNT.IconUrl = (IconPath);
                if (isNav == true)
                {
                    if (dr["TARGET"].ToString() != "")
                    {
                        TNT.NavigateUrl = dr["TARGET"].ToString() + ".aspx";
                    }
                }
                TNT.EnableClickEvent = true;
               
                TV.Nodes.Add(TNT);
                NodeRecursion(TNT, dr["ID"].ToString(), isNav);
                TV.ExpandAllNodes();
            }
        }
    }

    private static void NodeRecursion(TreeNode TNP, string TND, bool isNav)
    {
        DataRow[] dr = DtTree.Select("P_ID ='" + TND + "' ");
        if (dr.Count() > 0)
        {
            TNP.Nodes.Clear();
            for (int i = 0; i < dr.Count(); i++)
            {
                TreeNode tn1 = new TreeNode();
                tn1.Text = dr["NAME"].ToString();
                tn1.NodeID = dr["ID"].ToString();
                string IconPath = "~/extjs/res/icon/";
                if (dr["ICON"].ToString() == "")
                {
                    IconPath = IconPath + "folder" + ".png";
                }
                else
                {
                    IconPath = IconPath + dr["ICON"].ToString() + ".png";
                }
                tn1.IconUrl = (IconPath);
                if (isNav == true)
                {
                    if (dr["TARGET"].ToString() != "")
                    {
                        tn1.NavigateUrl = dr["TARGET"].ToString() + ".aspx";
                    }
                }

                tn1.EnableClickEvent = true;

                TNP.Nodes.Add(tn1);
                NodeRecursion(tn1, dr["ID"].ToString(), isNav);
            }
        }
    }


}

End--------------------------PageHelper.cs-------------------------------------------



-------------------------Default.aspx.cs-------------------------------------------

protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            if (DomainCheck("EXAS", "CQE") == true)
            {
                Init_left_tree();
                get_name();
                Alert.Show(u_name+" "+u_title+" 欢迎回来。","Computer Assisted Management System 3.0",MessageBoxIcon.Information);
            }
            else
            {
                Alert.Show("请使用有效的域账户登陆操作系统。", "", MessageBoxIcon.Warning);
            }
        }
    }

    protected void leftMenuTree_NodeCommand(object sender, TreeCommandEventArgs e)
    {
        //Session.Add("target", leftMenuTree.SelectedNode.NavigateUrl);
        HttpCookie cookie = new HttpCookie("target");
        cookie.Value = leftMenuTree.SelectedNode.NavigateUrl;
        cookie.Expires = DateTime.Now.AddDays(1);
        HttpContext.Current.Response.Cookies.Add(cookie);
    }

End-------------------------Default.aspx.cs-------------------------------------------


-------------------------子页面-------------------------------------------------------
protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            if (PageHelper.Check_page(this.Page) == false)
            {
                Response.Redirect("~/NoAuth.aspx");
            }
        }
    }
End-------------------------子页面-------------------------------------------------------

作者: zy32002    时间: 2017-6-30 17:47
写个basepage页面,每个页面都继承这个basepage。在basepage里获取页面url,根据权限判断当前用户是否有权进入此页面。无权,respone.end()
作者: 898806387    时间: 2017-6-30 18:28
zy32002 发表于 2017-6-30 17:47
写个basepage页面,每个页面都继承这个basepage。在basepage里获取页面url,根据权限判断当前用户是否有权 ...

凡是在子页面之外写的语句,在地址栏直接敲子页面的地址,都可以绕开的
作者: 898806387    时间: 2017-6-30 18:29
zy32002 发表于 2017-6-30 17:47
写个basepage页面,每个页面都继承这个basepage。在basepage里获取页面url,根据权限判断当前用户是否有权 ...

凡是在子页面之外写的代码,在地址栏直接敲子页面的地址时,都是可以绕开的。
我觉得还是得想个办法,点treenode的时候做一下标记,在子页面load的时候对比这个标记,如果没有,就证明是直接敲地址进的
作者: sanshi    时间: 2017-6-30 21:27
898806387 发表于 2017-6-30 18:29
凡是在子页面之外写的代码,在地址栏直接敲子页面的地址时,都是可以绕开的。
我觉得还是得想个办法,点t ...

这个真没必要,URL就是让人访问的,只要不是越权访问都不应该禁止
作者: 898806387    时间: 2017-7-1 00:37
sanshi 发表于 2017-6-30 21:27
这个真没必要,URL就是让人访问的,只要不是越权访问都不应该禁止

比如说,我的tree菜单指向的链接有普通用户用的、有系统设置的、有人力资源的、有财务的。第一步,通过数据库查询,只生成用户有操作和查看权限的tree,但是仍然需要防范用户知道页面地址后敲地址绕过tree获取权限。当然,如果控件实现不了,可以在子页面load时再从数据库查询一次是否有权限,不过,如果控件能实现,便减少了读取数据库,提高效率
作者: zy32002    时间: 2017-7-1 09:53
你怎么标记? url直接能访问到,怎么判断是否可以有权限。我一个普通员工直接财务页面操作,这安全??
再有你这你是权限的问题,和tree一点关系没有,就别提什么tree。
作者: zy32002    时间: 2017-7-1 09:56
再有cookie都可以伪造的,不安全不推荐
作者: 898806387    时间: 2017-7-2 11:33
zy32002 发表于 2017-7-1 09:56
再有cookie都可以伪造的,不安全不推荐

用cookie是因为session容易丢,会在这方面改进一下,比如使用数据库存session
作者: 898806387    时间: 2017-7-2 11:39
zy32002 发表于 2017-7-1 09:53
你怎么标记? url直接能访问到,怎么判断是否可以有权限。我一个普通员工直接财务页面操作,这安全??
再 ...

我已经说了怎么标记的思路,也写了实现方法。现在的问题是navigateurl优先于nodecommand执行而无法给标记赋值,跟tree当然有关。所以请教大家有没有别的方案。请:1没必要评论需求的合理性,2看完别人的帖子再评论,3应该讨论的是技术上的实现方法,而不是别的。
作者: zy32002    时间: 2017-7-3 09:20
898806387 发表于 2017-7-2 11:39
我已经说了怎么标记的思路,也写了实现方法。现在的问题是navigateurl优先于nodecommand执行而无法给标记 ...

1 首先我们没有你的环境,不知道什么问题,再有你没说清楚。
2 我很负责的告诉你我已经认真的看你的帖子。你这问题就是 “怎么跳窗户进屋子?” 我们正常人当然会问为什么不走门。
3 如果是session丢失的问题,可以设置把session的加密的值和失效的时间放入到cookie里,从新写回到session。
navigateurl只是属性,我不确定在这个属性里注入js会不会好用,具体看js生成的代码。这2种方式,我更倾向于cookie里从写session
作者: 898806387    时间: 2017-7-3 13:02
zy32002 发表于 2017-7-3 09:20
1 首先我们没有你的环境,不知道什么问题,再有你没说清楚。
2 我很负责的告诉你我已经认真的看你的帖子 ...

1  2、3楼有详细的说明,还有代码,虽然没有数据库,应该能看的明白
2 不是“怎么跳窗户进屋子”,而是怎么防止别人跳窗户进屋子。

再说一遍,希望能帮助你理解:
我的tree是根据权限表生成的,用户没有权限的节点就不会出现,这是控制权限的第一步,对于通常情况是足够了。
但是如果用户别有用心,从别的电脑看到了地址,可以不使用tree,直接敲地址进入页面,如果在各个页面的page_load里加一个判断,判断页面地址是不是与tree.selectednode某个值一致。

首先,我不觉得这个需求不正常,如果你有更好的解决方案,欢迎交流。如果没有想到这一层,免费拿走。
其次,在实现方法上有很多种,我也不纠结于这一种思路。目前就是在各个页面再查询一次权限表进行判断,想使用session或者cookie存selectednode的思路,只是为了提高执行效率、减少访问数据库。如果有更好的实现方法,欢迎交流。
作者: zy32002    时间: 2017-7-3 16:12
898806387 发表于 2017-7-3 13:02
1  2、3楼有详细的说明,还有代码,虽然没有数据库,应该能看的明白
2 不是“怎么跳窗户进屋子”,而是怎 ...

在4楼我已经回答你 怎么防止别人跳窗户进屋子。
至于减少访问数据库提升效率,我是用 cache缓存权限。
获取当前访问页面的url,在缓存里看看当前的用户是否有这个url,有则有权限,否则无权限。
作者: 898806387    时间: 2017-7-5 16:51
zy32002 发表于 2017-7-3 16:12
在4楼我已经回答你 怎么防止别人跳窗户进屋子。
至于减少访问数据库提升效率,我是用 cache缓存权限。
获 ...

不论用什么存,你是往cache里写吗? 什么时候写?nodecommand吗?
navigateurl优先于nodecommand执行,跳到你的目标页面,
不论你用什么方法判断,你是用basepage吗?
这个时候你的cache里还没有写进来东西,判断的结果显而易见
作者: zy32002    时间: 2017-7-6 09:22
898806387 发表于 2017-7-5 16:51
不论用什么存,你是往cache里写吗? 什么时候写?nodecommand吗?
navigateurl优先于nodecommand执行,跳 ...

创建权限角色的时候,我就把权限放到cache里。用户登录后根据权限角色,和cache里的权限进行比对。
只要是页面继承了basepage都进行这样的权限比对规则。
不用写什么nodecommand,他也阻止不了直接跳窗户;我不点击node,有权限却不能直接访问页面,这也不科学。
你这是页面级别上权限,如果是button级别的权限,我想知道你怎么处理。
作者: 898806387    时间: 2017-7-7 00:05
zy32002 发表于 2017-7-6 09:22
创建权限角色的时候,我就把权限放到cache里。用户登录后根据权限角色,和cache里的权限进行比对。
只要 ...

有道理,既单独判断又不读数据库。我后来不想读表,写了个存储过程返回判断结果...还是cache好。谢谢
作者: 898806387    时间: 2017-7-7 00:42
zy32002 发表于 2017-7-6 09:22
创建权限角色的时候,我就把权限放到cache里。用户登录后根据权限角色,和cache里的权限进行比对。
只要 ...

有道理,既单独判断又不读数据库。我后来不想读表,写了个存储过程返回判断结果...还是cache好。谢谢




欢迎光临 FineUI 官方论坛 (https://fineui.com/bbs/) Powered by Discuz! X3.4