【问题标题】:How to authenticate exist-db users in RESTXQ如何在 RESTXQ 中验证存在数据库用户
【发布时间】:2017-11-30 16:19:09
【问题描述】:

(完全改写 - 因为没有答案): 我正在开发一个带有用户身份验证和 RESTXQ 的存在数据库应用程序。我的用户通过登录模块中的 login:set-user 功能登录。这是来自控制器的 sn-p:

import module namespace login="http://exist-db.org/xquery/login" at "resource:org/exist/xquery/modules/persistentlogin/login.xql";

declare variable $local:login_domain := "org.exist-db.superApp";
declare variable $local:user := $local:login_domain || '.user';

let $logout := request:get-parameter("logout", ())
let $set-user := login:set-user($local:login_domain, (), false())

这工作得很好。如果我打电话给例如xmldb:get-current-user() 在 app:function() 中的任何位置我得到当前登录的用户名。

我还有一个 RESTXQ 模块,其中有几个函数可以通过 AJAX 请求通过 URL 动态调用。其中一些操作(删除数据中的 xml 元素,添加新集合...)相当关键。我不希望客人(或具有错误权限的用户)能够只调用这些 RESTXQ URL 来操作数据 - 所以 RESTXQ 必须是安全的,它应该仔细检查:当前登录的用户是否允许修改特定资源/收藏?

如果我打电话给例如xmldb:get-current-user() 在任何 RESTXQ 函数中,我总是得到“guest”,所有安全管理器 (sm) 函数也表明在 RESTXQ 中不知道当前用户登录。仅当我在每个 RESTXQ 函数中执行 xmldb:login("/db","username","password") 之类的操作时,RESTXQ 似乎知道有人已登录,但用户名和密码不应不断地通过来回传递URL - 但是如果不传入这些数据,RESTXQ 函数似乎并不知道它(对吗?)。

那么我如何确保 RESTXQ 只允许经过身份验证的用户更改数据(用户无需进行多次身份验证,也无需在每次请求时将身份验证数据传递给 RESTXQ)?

示例用例: 我想要一个 RESTXQ 函数,它获取一个搜索字符串 ($text) 和一个集合路径 ($path) 作为输入,现在它检查 $path 中的所有 xml 文件:如果当前登录的用户 (必须经过身份验证!)对文件具有写入权限,删除所有包含 $text 的节点并向用户返回一些 JSON 响应...

我有多个这样的功能,(移动、删除和添加数据,添加新集合...),除了粗体部分之外,它们运行良好:我没有得到这个 If。任何想法?

PS:topic on the eXist mailing list 提出了同样的问题。这里@adamretter 建议限制 RESTXQ 模块文件本身,因此在调用函数时会提示用户(重新)进行身份验证 - 即使他们已经使用了持久登录。这是我不喜欢的:

  1. 我不希望我的用户必须多次登录(这是让事情尽可能动态的想法 - 例如通过使用 RESTXQ)
  2. 现在通过登录模块提示的登录(用于执行 RESTXQ)和之前的登录(持久性)可能不同了!
  3. 即使用户在应用程序中注销,RESTXQ 仍然被授予访问权限,因为提示的身份验证对注销一无所知。如果一个新用户登录(不是在提示中,而是通过登录模块),她仍然可以访问 RESTXQ,因为这不是重新提示(而且我不知道如何“注销”这个提示,看似平行的第二个登录)。
  4. 我可以通过这种方式限制整个 RESTXQ 模块,但我仍然不知道如何在 RESTXQ 函数中询问:“当前用户对资源 A、B、C 有什么访问权限...

【问题讨论】:

  • @j-schäuble 我今天面临着您一年前发布的完全相同的问题。你是怎么解决的?谢谢!

标签: authentication exist-db securitymanager restxq


【解决方案1】:

希望这对其他人有所帮助:

在发出 AJAX 请求时,添加一个标头:

[...]
headers: {'Authorization': 'Basic ' + btoa(username + ':' + password)},
[...]

这将使用给定的凭据(如果正确)登录用户。然后,在您的 RESTXQ 函数中,您可以通过 sm:id() 访问用户的详细信息:

declare namespace sm = "http://exist-db.org/xquery/securitymanager";
[...]
let $username := xs:string(sm:id()//sm:real//sm:username)

您应该使用sm:real 下的信息作为setuidsetgid 可能会掩盖真实值。

请注意,登录信息不会被存储,因此您需要将它们与您发出的每个 AJAX 请求一起发送。

【讨论】:

  • btoa 部分可能为我节省了几个小时,非常感谢。这方面的文档非常稀缺......
【解决方案2】:

RESTXQ API 是无状态的。因此,您需要对每个请求进行身份验证。这是有意为之,并且是按设计完成的,以便每个 RESTXQ 调用都可以有效地独立工作。

这并不罕见,因为亚马逊的 S3 等其他 API 也要求在每个请求上提供此类身份验证。

您的用户如何向 RESTXQ 进行身份验证以及如何提示他们输入请求凭据(并可能重复使用这些凭据)超出了 RESTXQ API 的范围,而是被视为您需要自行解决的客户端问题应用。

【讨论】:

    猜你喜欢
    • 2010-09-21
    • 1970-01-01
    • 2020-02-28
    • 2014-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多