【问题标题】:Session management between thick client and server?胖客户端和服务器之间的会话管理?
【发布时间】:2011-01-20 15:00:37
【问题描述】:

我的应用程序是一个 Eclipse 富客户端,我想向其中添加身份验证和授权功能。我的用户和角色存储在数据库中,我的应用程序还有一个基于 Web 的管理控制台,可以让我管理用户和角色。我在这个管理控制台上利用 Spring 安全性。

所以这是我的要求:

我希望我的胖客户端为用户提供一个登录对话框。身份验证需要在服务器端执行(它可以是 Web 服务),并且角色必须流入胖客户端。我还想以某种方式在服务器端管理会话。

我真的想不出任何简单的方法来做到这一点。我知道如果我要使用 Spring Rich Client,它将与服务器端的 Spring Security 很好地集成。 但是,目前这不是我的选择。

请分享您对如何实现这一目标的想法。感谢您的帮助。

【问题讨论】:

    标签: java spring authentication eclipse-rcp thick-client


    【解决方案1】:

    由于您倾向于 Web 服务(听起来像您),我会考虑从您的富客户端(我假设用户 ID 和密码)获取用户信息,使用 WS-Security 将加密信息发送到Web 服务,并让 Web 服务执行身份验证。此外,我会考虑 Web 服务返回您想要返回到富客户端的有关用户的任何信息(名字/姓氏等)。

    【讨论】:

    • @SOA Nerd 问题是,如果我要从 web 服务返回东西——我该怎么做?将 xml 发送回胖客户端?然后呢?谁维护会话?这个问题更多的是如何提问
    • @Jay - 任何会话信息都应该在胖客户端上维护,服务器是无状态的。当 Web 服务返回时,它将在 SOAP/Rest 消息(XML 格式)中包含您的信息。对于 Web 服务客户端,我通常使用 JAXB 或 Axis2 来帮助我将此有效负载解组为我想要的 Java 对象,但这对于您所描述的内容可能有点过分了。在您的情况下,您可能只需要像 XPath 这样简单的东西。
    • “任何会话信息都应该在胖客户端上维护,服务器是无状态的”——我想在这里有所不同。您将如何在客户端获得状态信息?如果我想阻止用户从 2 台机器(使用同一个客户端)登录怎么办。没有办法控制这一点。没有什么可以为您提供有关谁登录等的统计信息。此外,这是客户端的很多安全代码,这是我想避免的。
    • 有状态服务器的扩展性不如无状态服务器,会话管理令人头疼(也是资源泄漏的根源)。将状态保留在客户端上。您有一个胖客户端 - 您已经付出了代价(需要桌面部署),因此可以获得一些好处,例如轻松的客户端存储。
    【解决方案2】:

    我最近使用Challenge-Response-authentication 开发了一个类似的应用程序。基本上,您的网络服务或服务器上有三种方法

    getChallenge(username) : challenge
    getSession(username, response) : key
    getData(username, action?) : data
    

    getChallenge 返回一个值(例如一些随机值或时间戳),客户端使用他/她的密码散列并发送回 getSession。例如,服务器将用户名和挑战存储在地图中。

    在 getSession 中,服务器计算相同的哈希值并与来自客户端的响应进行比较。如果正确,则生成、存储会话密钥并将其发送到使用用户密码加密的客户端。现在每次调用 getData 都可以使用会话密钥加密数据,并且由于客户端已经在 getSession 中验证,他/她不必再次“登录”。

    这样做的好处是密码永远不会以纯文本形式发送,如果有人在听,由于密码是用随机值散列的,对 getSession 的调用将很难伪造(通过重播对实例)。由于来自 getSession 的密钥是使用用户密码加密发送的,因此犯罪者必须知道密码才能破译它。最后,您只需验证用户一次,因为对 getData 的调用会使用用户会话密钥对数据进行加密,然后就不必再“关心”了。

    【讨论】:

      【解决方案3】:

      我认为我有类似的要求。在我们的例子中:

      • 用户在登录时提供用户名和密码
      • 对照 USER 表检查此项(顺便说一句,密码不是纯文本)
      • 如果有效,我们希望会话持续 20 分钟;我们不想在胖客户端每次执行检索数据或存储数据时检查用户名和密码(我们可以这样做,事实上这不会是世界末日,但这是不必要的额外数据库操作)

      在我们的例子中,我们有很多权限需要考虑,而不仅仅是一个布尔值“有或没有访问权”。我想做的是生成一个全局唯一的会话令牌/密钥(例如 java.util.UUID),胖客户端将其保留在某种本地 ThickClientSession 对象中。

      每次胖客户端启动操作时,例如调用 getLatestDataFromServer(),此会话密钥被传递给服务器。

      应用服务器(例如运行在 Tomcat 下的 Java webapp)本质上是无状态的,除了这个会话密钥的记录。如果我在上午 10 点登录,那么应用服务器会将会话密钥记录为在上午 10:20 之前有效。如果我在上午 10:05 请求数据,会话密钥有效期将延长到上午 10:25。会话附带的各种特权级别也保持状态。这可以通过一个以 UUID 为键的简单 Map 集合来完成。

      关于如何进行这些调用:我推荐 Spring HTTP Invoker。这很棒。您不需要成熟的 Spring Rich Client 基础架构,它可以很容易地集成到任何 Java 客户端技术中;例如,我正在使用 Swing 这样做。出于安全目的,这可以与 SSL 结合使用。

      无论如何,这就是我计划解决的大致方法。希望这有点用!

      【讨论】:

        【解决方案4】:

        也许这会对你有所帮助:

        http://prajapatinilesh.wordpress.com/2009/01/14/manually-set-php-session-timeout-php-session/

        特别注意这一点(用于强制垃圾回收):

        ini_set(’session.gc_maxlifetime’,30);
        ini_set(’session.gc_probability’,1);
        ini_set(’session.gc_divisor’,1);
        

        还有一个名为 session.cookie_lifetime 的变量,您可能也需要对其进行更改。

        IIRC,您必须设置至少 2 个(可能更多)变量。我这辈子都不记得它们是什么了,但我确实记得不止 1 个。

        【讨论】:

        • 这与我的问题无关。我现在的服务器端是 Spring(spring security)。当胖客户端连接到网络服务器时 - 我不确定如何处理安全部分。
        猜你喜欢
        • 2015-06-01
        • 2015-08-06
        • 2016-12-01
        • 1970-01-01
        • 2016-05-03
        • 1970-01-01
        • 2010-11-28
        • 2023-03-12
        • 2011-07-19
        相关资源
        最近更新 更多