如何从 url 中提取在 Scala Play 中用 # 分隔的参数

How to extract arguments from url that are separated with # in Scala Play

我正在 Scala Play 中实施离线 Google OAuth 流程。

用户点击对话 "yes I want this application to access the following data of my Google account..."。用户单击“确定”后,Google 服务器向我的服务器发送一个令牌。 示例响应如下所示(URL 我的浏览器 window):

https://myapp.herokuapp.com/storeauthcode#code=123&login_hint=abc&client_id[crypticId].apps.googleusercontent.com&prompt=consent

如何在当前浏览器 window 中从当前 url 中提取 123 子字符串(这是我的访问令牌)?:

def storeAuthCode = Action { request =>

    //save token
    //confirm login of user now
  }

提取查询参数之类的数据当然行不通。

request.path

returns

/storeauthcode

但不是带有标记的字符串。

URL 在 # 之后的部分称为 fragment identifier。片段标识符没有被浏览器发送到服务器:

The fragment identifier functions differently than the rest of the URI: namely, its processing is exclusively client-side with no participation from the web server — of course the server typically helps to determine the MIME type, and the MIME type determines the processing of fragments. When an agent (such as a Web browser) requests a web resource from a Web server, the agent sends the URI to the server, but does not send the fragment. Instead, the agent waits for the server to send the resource, and then the agent processes the resource according to the document type and fragment value.

如果有必要,您可以在客户端解析出片段,然后将其作为请求正文或查询字符串的一部分发送。

这个问题的另一个相关答案是@slashburn 使用的 OAuth2 流程对于用例来说是不正确的。 Google 将此流程称为“OAuth 2.0 for Client-side Web Applications”。此流程仅供可以读取片段的客户端浏览器应用程序使用。当浏览器客户端请求 "token" 的 response_type 时启动流程。

https://accounts.google.com/o/oauth2/v2/auth?
redirect_uri=http%3A%2F%2Foauth2.example.com%2Fcallback&
response_type=token&
client_id=client_id

代替客户端流程使用的适当流程是“OAuth 2.0 for Web Server Applications”。此流程适用于使用 Web 服务器与 google api 交互的 Web 应用程序。 response_type 的值不是 "token",而是 "code".

https://accounts.google.com/o/oauth2/v2/auth?
redirect_uri=http%3A%2F%2Foauth2.example.com%2Fcallback&
response_type=code&
client_id=client_id

这个流程有点复杂,因为 OAuth2 服务器会发回一个临时代码。然后服务器直接使用临时代码 POST 到 OAuth2 服务器,以使用 url 和如下所示的正文取回令牌。

https://www.googleapis.com/oauth2/v4/token

POST /oauth2/v4/token HTTP/1.1
Host: www.googleapis.com
Content-Type: application/x-www-form-urlencoded

code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=your_client_id&
client_secret=your_client_secret&
redirect_uri=https://oauth2.example.com/code&
grant_type=authorization_code

服务器和客户端应用程序使用不同流的原因是为了防止通过网络明文传输访问代码。对于客户端流,片段完全位于浏览器本地,因此攻击者无法嗅探到任何东西。对于服务器流程,攻击者只能看到一次性代码。没有服务器的秘密,一次性代码是无用的。服务器在其主体中发布代码和秘密以从服务器获得响应,并且通信的两部分均由 HTTPS 协议加密。