从请求URL中获取哈希参数

28

看看这个。基本上 # 后面的任何内容都不会发送到服务器,所以它对此一无所知。这个人所做的是在处理请求的服务器端点中注入了一些 JavaScript,然后从 URL 获取数据并将其发送回服务器。 https://github.com/sosodev/twitchOAuth/blob/main/twitchoauth.go#L28 - Ari
8个回答

33

在客户端(即从JavaScript中),您可以检查window.location.hash以获取哈希值。在服务器端,一般的答案是“不可能”,因为哈希值不会随请求发送到服务器。

更新:我可能误解了问题。我的答案是关于如何在浏览器或服务器端代码中获取URL的哈希部分,在处理请求期间,而不是关于字符串处理的。

更新2:在此回答评论,因为评论中无法放得下。

当用户单击您的导航链接时,它是如何工作的?

我假设哈希值被更改,并通过来自Web服务或REST的AJAX请求下载相应的内容。

例如,如果您的用户在浏览器中具有www.example.com的网址,并且此页面显示产品类别列表。用户单击一个类别,URL会更改为www.example.com/#id=5,并通过AJAX下载该类别的产品(ID = 5)并显示在页面上。没有PostBack,只有部分页面刷新。

这与您的方案接近吗?

现在您希望用户直接在浏览器地址栏中粘贴/输入www.example.com/#id=5并直接转到该类别的产品列表。

但是,/#id = 5不会随请求一起发送到服务器,因此无法在服务器端获取该值,并且您无法对此做任何事情,因为这是浏览器决定不发送此数据,而您在服务器端没有该数据。

在我们的项目中,我们使用以下解决方案:服务器仅返回常见页面代码/ HTML,即页眉和页脚,没有页面的主要/中心部分。然后有一个JavaScript代码,在此公共HTML加载后立即执行。它获取window.location.hash并通过AJAX将其发送到Web服务,Web服务返回页面主体内容(HTML)。


让我解释一下:我使用了ajax导航在某个网站上。后来,我决定使用jQuery BBQ库,以便能够将所有步骤存储在浏览器的历史记录中。现在我想创建这样的事情-如果用户转到默认页面-就会生成一些列表。如果他去到/#id=5,服务器应该生成另一个内容。所以我的问题是,我无法在服务器端读取#id的值。 - nKognito
我已经在答案本身的UPD2中回答了。 - Insomniac
谢谢Kyrill,我遇到了你描述的完全相同的问题。在你的解决方案中,我不喜欢向服务器发送双倍或者三倍的AJAX请求,但显然这是一个单一的解决方案。谢谢。 - nKognito

15

1
那么,你如何首先获得/abc#xyz呢? - Bojan Krkic
1
最初提出的问题并没有涉及客户端/服务器/浏览器或其他任何事情。它只是说你有这个URL字符串,如何提取片段,这就是我的答案所涵盖的内容。 - ptomli
从技术上讲,是的,没错。但那只是一个字符串操作 ¯\_(ツ)_/¯ - Bojan Krkic

0

以下是如何捕获锚链接的方法。适用于所有的Web框架。

我将使用一个示例场景来说明:假设我们需要捕获由未经身份验证的用户请求的深度URL http://server.com/#/xyz,以便他们在登录后被重定向到该深度URL。

  1. 未经身份验证的用户请求http://server.com/#/xyz(从“#”开始的所有内容都不会发送到服务器)。

  2. 服务器只知道用户想要http://server.com/,并且他们未经身份验证。服务器将用户重定向到登录表单。

  3. 这是聪明的部分:客户端仍在等待其原始请求,因此如果服务器在登录表单中包含一个带有一些JS的隐藏元素,该JS引用window.location.href,则可以捕获完整的URL 原始请求连同锚点部分:

    <form action="/login" method="post">
      <div>
        <label>Username:</label>
        <input type="text" name="username"/><br/>
      </div>
      <div>
        <label>Password:</label>
        <input type="password" name="password"/>
      </div>
      <!-- XXXXXXXXX 聪明的部分 XXXXXXXXXX-->
      <script>
        document.write('<input type="hidden" name="from" value="'+document.location.href+'"/>');
      </script>
      <!-- XXXXXXXXXX-->
      <div>
        <input class="submit-button" type="submit" value="Submit"/>
      </div>
    </form>
    
  4. 用户进行身份验证,原始URL随POST一起发送。然后服务器可以将用户中继到原始深度URL。


-1

你正在使用什么来做这个?

如果你正在使用JSP或Servlet,以下内容将对你有用。

if (request.getParameter("#id") == null) {
    out.println("Please enter your name.");
} else {
    out.println("Hello <b>"+request.getParameter(i)+"</b>!");
}

如果你正在使用 JavaScript,以下函数将对你有用

function getURLParameters() 
{
var sURL = window.document.URL.toString();

if (sURL.indexOf("?") > 0)
{
    var arrParams = sURL.split("?");

    var arrURLParams = arrParams[1].split("&");

    var arrParamNames = new Array(arrURLParams.length);
    var arrParamValues = new Array(arrURLParams.length);

    var i = 0;
    for (i=0;i<arrURLParams.length;i++)
    {
        var sParam =  arrURLParams[i].split("=");
        arrParamNames[i] = sParam[0];
        if (sParam[1] != "")
            arrParamValues[i] = unescape(sParam[1]);
        else
            arrParamValues[i] = "No Value";
    }

    for (i=0;i<arrURLParams.length;i++)
    {
        alert(arrParamNames[i]+" = "+ arrParamValues[i]);
    }
}
else
{
    alert("No parameters.");
}
   }

2
似乎没有任何方法可以在服务器端读取哈希变量。 - nKognito
如果您想在服务器端读取它,servlet 可以实现此功能,它会在服务器端提供参数,如第一个代码片段所示。通过 servlet,您将获得 HttpRequest 对象请求,通过它可以获取其参数。 - Hemant Metalia
request.getParameter("#id"),request.getAttribute("#id") 不起作用。 - nKognito
没有任何错误。它返回 null。我正在使用 Spring MVC。因此,我正在尝试在控制器方法中获取请求参数。 - nKognito
让我们在聊天中继续这个讨论:http://chat.stackoverflow.com/rooms/4774/discussion-between-nkognito-and-hemant-metalia - nKognito
显示剩余2条评论

-1
String url = " http://www.coolsite.com/daily-plan/#id=1";
int sharpPos = url.indexOf('#');
String q = null;
if (sharpPos >= 0) {
    q = url.substring(sharpPos);
}

当然,您可以使用各种字符串操作方法,包括正则表达式。

但实际上,您的示例很奇怪。通常,在问号后传递URL参数。在这种情况下,您只需使用标准类URL:

String q = new URL(" http://www.coolsite.com/daily-plan?id=1").getQuery();


我同意通常看到参数在问号后面传递。然而,有时我也看到它作为哈希传递...但很少在更复杂的代码中出现。 - Mike Kormendy

-2

在解析URL时,将'#'替换为'?'。请查看下面的代码

String url = "http://www.coolsite.com/daily-plan/#id=1";
String urlNew = url.replace("#", "?");
String id = Uri.parse(urlNew).getQueryParameter("id");

4
这段代码显然没有考虑到URL中已经存在的查询参数……我建议不要采用这种解决方案,因为它误用了一个概念,并且只适用于特殊情况。 - jbspeakr

-3
如果您的URL与您编写的内容相同且不包含任何其他内容,则以下Java代码将对您有所帮助。
 String val = "http://www.coolsite.com/daily-plan/#id=1";
 System.out.println(val.split("#id")[1]);

不要忘记检查空值。

P.S. 如果您使用servlet,可以从request.getAttribute("id")获取此参数。

最好的祝福, Psycho


1
request.getParameter("#id"),request.getAttribute("#id") 不起作用。 - nKognito
由于您的URL不正确,无法在servlet上获取参数。例如,如果URL是"http://www.coolsite.com/daily-plan/?id=1",则我的示例代码将起作用并提供您的参数(request.getAttribute("id"))。 - Psycho
我知道我的URL不正确。实际上它是正确的,但是传递参数不正确。所以我的问题是 - 是否有任何方法可以在服务器端读取那个#id参数? - nKognito
不,这个参数默认情况下不会发送到服务器。但是你只能在客户端获取此参数并手动将其发送到服务器。你是如何调用你的servlet的?使用HTML表单还是调用jQuery方法? - Psycho
问题在于,我正在使用jQuery BBQ插件以启用浏览器的后退按钮。但是当我首次调用页面时 - 内容已经在服务器端生成。 - nKognito

-3
如果您的URL是从OAuth回调中获取的,那么您就无法这样做!因为完整的URL由于哈希符号(#)而无法发送到服务端。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接