使用会话 Id 或用户名 + 密码进行 Shiro 身份验证

2022-09-03 09:46:34

我在Java身份验证框架和身份验证工作流程方面没有太多经验(只有一些理论知识),因此出于教育目的,我正在尝试为我的HTTP应用程序创建这种类型的身份验证:

  1. 客户端将登录名 + 密码发布到 。/login
  2. Shiro 通过给定的凭据登录用户。服务器返回客户端他的 .sessionId
  3. 客户端请求某种资源 。/myresource?sessionId=1234567
  4. 四郎在主题中由给定.然后服务器执行获取的常规工作流(Shiro管理方法级访问权限)。sessionId/myresource

基本上我有这些问题:

  1. 我想我不需要HTTP会话,也不需要Servlet会话。Shiro有自己的会话管理器,足以满足我的需求。我错了吗?
  2. 是否为客户端提供真正的 sessionId 是很好的做法,还是应该发送某种 sessionToken(在服务器端解析为 sessionId)?
  3. 如何使用会话 Id(客户端应将其存储在本地)登录主题?
  4. 在执行此类身份验证之前,我还需要了解其他事项吗?

提前致谢。


答案 1

我想我不需要HTTP会话,也不需要Servlet会话。Shiro有自己的会话管理器,足以满足我的需求。我错了吗?

不,你是对的。这就是为什么Shiro很棒。从文档中

Shiro 的 Session 支持比这两种 [Web 容器或 EJB Stateful Session Bean] 机制中的任何一种更易于使用和管理,并且无论容器如何,它都可以在任何应用程序中使用。

例如:

Subject currentUser = SecurityUtils.getSubject();    
Session session = currentUser.getSession();
session.setAttribute( "someKey", someValue);

引用自文档getSession calls work in any application, even non-web applications

是否为客户端提供真正的 sessionId 是很好的做法,还是应该发送某种 sessionToken(在服务器端解析为 sessionId)?

发送普通的会话 Id 是一个坏主意。特别是,如果您通过未加密的网络发送数据。要么使用类似HTTPS的东西,要么使用NONCE行的东西

而且,旁注,如果通过http / s POST数据而不是将其放在URL中。

如何使用会话 Id(客户端应将其存储在本地)登录主题?

您的意思是,一旦您拥有会话ID,如何对主题进行身份验证?您可以简单地从文档中,

Subject requestSubject = new Subject.Builder().sessionId(sessionId).buildSubject();

在执行此类身份验证之前,我还需要了解其他事项吗?

是的。

  1. 阅读 Shiro 的会话管理
  2. 精益关于MITM攻击
  3. 关于 HTTPSSSL
  4. 一些关于哈希函数这个Apache Commons DigestUtils和可能是这个

更新

关于该主题身份验证部分 - 它是否会使新创建的主题成为当前经过身份验证的主题?如果没有,我如何使其成为“当前”主题?

如果你在谈论,它不会。我不知道如何将其设置为线程的当前用户。Shiro的JavaDoc说:new Subject.Builder().sessionId(sessionId).buildSubject()

[这样]返回的 Subject 实例不会自动绑定到应用程序(线程)以供进一步使用。也就是说,SecurityUtils.getSubject() 不会自动返回与生成器返回的实例相同的实例。如果需要,框架开发人员可以绑定构建的主题以继续使用。

因此,这取决于您如何在当前线程或进一步使用中绑定主题。

如果你担心事情是如何工作的,那么,在Web容器上下文中,它使用简单的cookie来存储你的会话数据。当您的请求通过 Shiro 过滤器发出时,它会将当前主题附加到其生命周期(当前线程)的请求中。当你只是得到从请求。我在这里发现了一个有趣的话题。SecurityUtils.getSubject();getSubject()Subject

关于nonce部分:如果他向我发送某种哈希而不是他的specationId - 我将无法对其进行解码以获得真正的specationId(授权他)。我在这里错过了什么吗?

Nonce部分 -- 这是脖子上的疼痛。现在重新思考,我认为做NONCE只是矫枉过正。无论如何,让我解释一些,

  1. 用户首次使用其用户名和密码登录。在客户端设置 、(例如 UUID),并调用 hash1。比如说,在饼干里。将其存储在服务器端,可能位于 DB 或 Map 中useridnonceHASH(sessionID+nonce)nonceuser_id <--> nonce,session_id

  2. 在后续请求中,请确保回传 ,并且 .useridnonceHASH

  3. 在服务器端,您要做的第一件事是验证请求。获取 和 存储在哈希映射或数据库中 基于客户端发送的哈希映射或数据库。创建一个哈希,HASH(sessionId_from_db+ nonce_from_db),称之为hash2。sessionIdnonceuser_id

  4. 现在,如果 hash1 与 hash2 匹配,则可以验证请求,并且由于已将当前 sessionId 存储在服务器端,因此可以使用它。请求完成后,在 cookie 和服务器端设置新的随机数。

如果您通过1 - 4,您将意识到您不需要Shiro进行身份验证。(:所以,我收回我的话,NONCE在这种情况下不适用,除非你对安全性而不是性能过于怪异。

为什么MITM攻击对我很重要?我的客户端(javascript ajax代码)通过ajax从它的服务器获取数据。所以我认为我不应该以任何方式关心MITM。

我认为这对你来说应该很重要。MITM攻击意味着您的请求/响应通过机器(MITM)链接到您的路由器。如果是未加密的请求,则它都是 MITM 的纯文本。他可以看到您的所有请求...并可能欺骗请求,并可能劫持会话。让我找一些例子....http://michael-coates.blogspot.com/2010/03/man-in-middle-attack-explained.html


答案 2

推荐