zoukankan      html  css  js  c++  java
  • [原創]另一種思路固定URL及.NET實現

    背景

    項目經常有這樣的需求:爲了安全需要向用戶隱藏URL。

    首先說明下這個需求如果是爲了安全則完全沒有理由,因為不可能隱藏了URL就安全了,對於瞭解一些HTTP原理的用戶,這個需求是掩耳盜鈴,當然隱藏後也並非沒有好處,起碼URL看上去乾淨整潔。其實也就是隱藏查詢字符串(QueryString),一些常見的做法如使用iFrame、URL重寫等,這裡就不討論了。

    如果把以上需求變成爲了乾淨整潔,不妨把隱藏URL變成固定URL更好。那麼URL重寫就不滿足需求了。

    知識

    一般的HTTP請求,大多是GET和POST請求,GET請求不管你服務器端如何如何,客戶端的URL是一定會變的。POST請求則要看頁面Form的Action,URL會變成Action的頁面。一般<a>標籤直接設置href後,點擊直接執行GET請求,請求href中的資源,form.submit則是執行POST請求。

    原理及實現

    一、

      既然GET請求一定會改變URL,那麼我們不可能實現客戶端第一次發起GET請求時固定URL,因為這是客戶端事件,我們只能GET後重定向到某一我們需要固定的頁面。可是重定向後頁面應該呈現什麽內容呢?我的做法是截獲所有GET請求,將請求的URL記錄到一個FORM中的隱藏字段,Form.Action是一個固定的頁面(這個頁面完全可以不真實存在),然後直接提交Form,發出POST請求,這樣子用戶的URL就變成了固定頁面。服務器再截獲POST請求,取得Request中記錄的原GET請求的URL,通過重寫URL獲得真正的頁面內容。

    .NET則是在Global.ascx中的 Application_BeginRequest實現截獲請求

    GET請求的處理,直接寫response完全不需要有index.aspx頁面的存在:

     1 StringBuilder html = new StringBuilder();
    2 html.Append("<form method=\"post\" id=\"form\">")
    3 .AppendFormat("<input type=\"hidden\" name=\"__POSTURL\" value=\"{0}\" />", Request.AppRelativeCurrentExecutionFilePath + Request.Url.Query + Request.PathInfo)
    4 .Append("</form>")
    5 .Append("<script>")
    6 .AppendFormat("form.action = \"{0}\"; form.submit();", Request.ApplicationPath.TrimEnd('/') + "/index.aspx")
    7 .Append("</script").Append(">");
    8 Response.Clear();
    9 Response.Write(html);
    10 Response.End();

    POST請求的處理,注意false參數固定了引用的url,沒有此參數會導致跨目錄頁面的stylesheet路徑不對而失效。

    1 HttpContext.Current.RewritePath(Request["__POSTURL"], false);


    二、

      實現了以上代碼後,在頁面中做POST請求,仍然會POST到原頁面,URL會變。這裡通過修改Form.Action實現POST到同一頁面,使用隱藏域記錄真正需要POST到的頁面,然後使用到前面POST請求的重寫URL而POST到隱藏域頁面。

    實現:在MasterPage(或者你的BasePage頁面)的Page_Load中:

    1 string actionUrl = Request.ApplicationPath.TrimEnd('/') + "/index.aspx";
    2 string postUrl = Page.AppRelativeVirtualPath + Request.Url.Query + Request.PathInfo;
    3 Page.Form.Action = actionUrl;
    4 Page.ClientScript.RegisterHiddenField("__POSTURL", postUrl)

    注意POSTURL一定要是相對路徑如“~/xxx/xxx.aspx”,因為RewritePath方法需要傳入相對路徑。

    三、

      以上已經實現了對GET和POST的固定URL處理,但是頁面中的超鏈接如果是直接GET,難免URL會閃動後變回固定URL,要避免這個只能通過項目要求不能直接使用簡單的GET跳轉(包括服務器端的Response.Redirect)。

    不用GET跳轉而用一個簡單特殊的POST跳轉,則完全可以做到URL紋絲不動,在需要跳轉的按鈕或者鏈接註冊.click事件:

    function postRedirect(url) {
    $("body").append('<form id="postForm" method="post" action="index.aspx"><input type="hidden" name="__POSTURL" value="' + url + '" /></form>');
    $("#postForm").submit();
    }

    以上只是一個簡單的例子,並不通用,需要注意、改善的地方有action的路徑,阻止控件的自身事件(preventDefault)阻止冒泡等,你也可以擴展傳入參數,通過隱藏域傳到要POST的頁面。

    後臺跳轉的話也可以模仿此JS方法或模仿截獲GET請求的那段代碼寫通用方法即可。也可以使用Server.Transefer等方式(未驗證)。

    以上方案可能存在一些問題,比如若使用了PostBackUrl則會失效,但解決方式也很簡單,比如提交前再更改form的action,直接使用自己擴展加了參數後的postRedirect做跨頁面提交而不使用PostBackUrl。本文也主要是提供另一個自己想到的思路,具體實現起來可能會有更好的方法。

    2012-1-10 補充:Response.Redirect處理

    服務器端使用Response.Redirect實際上就是向客戶端發送301或302跳轉響應,只要在EndRequest中攔截此Response并改成偽Post Form作為跳轉用途,再將StatusCode改成200(重要)即可。



  • 相关阅读:
    【转】ERROR: Cannot uninstall 'llvmlite'. It is a distutils installed project. 此类报错的解决办法
    【转】python setup.py install 报错:error:[WinError 3]系统找不到指定的路径: 'C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\PlatformSDK\\lib
    【转】距离相关系数以及python包的安装
    【转】算法总结这是一份全面并且详细的排序算法学习指南
    origin 一键导出文件夹中所有图形
    【转】距离相关系数的python实现
    [转]一文让你通俗理解奇异值分解
    origin 检查是否有重复图片
    【Vegas原创】centos网卡自启动
    【Vegas原创】使用dockercompose运行mysql8
  • 原文地址:https://www.cnblogs.com/sohobloo/p/2306264.html
Copyright © 2011-2022 走看看