对于最新的稳定版本,请使用 Spring Session 3.4.0! |
Spring Session - 按用户名查找
假设
本指南假定您已经使用内置的 Redis 配置支持将 Spring Session 添加到您的应用程序中。 该指南还假定您已经将 Spring Security 应用于您的应用程序。 但是,该指南在某种程度上是通用的,可以应用于任何技术,只需进行少量更改,我们将在本指南的后面讨论。
如果您需要了解如何将 Spring Session 添加到您的项目中,请参阅示例和指南列表 |
关于示例
我们的示例使用此功能使可能已泄露的用户会话失效。 请考虑以下场景:
-
用户转到库并向应用程序进行身份验证。
-
用户回家后发现他们忘记注销。
-
用户可以使用位置、创建时间、上次访问时间等线索从库中登录并结束会话。
如果我们能让用户从他们进行身份验证的任何设备在图书馆的会话中无效,那不是很好吗? 此示例演示了如何实现这一点。
用FindByIndexNameSessionRepository
要按用户名查找用户,您必须首先选择实现 FindByIndexNameSessionRepository
的用户名。
我们的示例应用程序假设 Redis 支持已经设置完毕,因此我们已准备就绪。SessionRepository
映射用户名
FindByIndexNameSessionRepository
如果开发人员指示 Spring Session 哪个用户与 相关联,则只能通过用户名找到会话。
为此,请确保 name 的 session 属性中填充了 username。Session
FindByUsernameSessionRepository.PRINCIPAL_NAME_INDEX_NAME
一般来说,您可以在用户进行身份验证后立即使用以下代码执行此操作:
String username = "username";
this.session.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, username);
向会话添加其他数据
最好将其他信息(如 IP 地址、浏览器、位置和其他详细信息)关联到会话。 这样做可以使用户更容易知道他们正在查看哪个会话。
为此,请确定要使用的会话属性以及要提供的信息。 然后创建一个添加为 session 属性的 Java Bean。 例如,我们的示例应用程序包括会话的位置和访问类型,如下面的清单所示:
public class SessionDetails implements Serializable {
private String location;
private String accessType;
public String getLocation() {
return this.location;
}
public void setLocation(String location) {
this.location = location;
}
public String getAccessType() {
return this.accessType;
}
public void setAccessType(String accessType) {
this.accessType = accessType;
}
private static final long serialVersionUID = 8850489178248613501L;
}
然后,我们使用 将该信息注入到每个 HTTP 请求的会话中,如下例所示:SessionDetailsFilter
@Override
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
chain.doFilter(request, response);
HttpSession session = request.getSession(false);
if (session != null) {
String remoteAddr = getRemoteAddress(request);
String geoLocation = getGeoLocation(remoteAddr);
SessionDetails details = new SessionDetails();
details.setAccessType(request.getHeader("User-Agent"));
details.setLocation(remoteAddr + " " + geoLocation);
session.setAttribute("SESSION_DETAILS", details);
}
}
我们获取所需的信息,然后在 .
当我们检索 by 用户名时,我们可以使用会话来访问我们的 session,就像我们访问任何其他 session 属性一样。SessionDetails
Session
Session
SessionDetails
您可能想知道为什么 Spring Session 不提供开箱即用的功能。
我们有两个原因。
第一个原因是应用程序自己实现这一点非常简单。
第二个原因是会话中填充的信息 (以及该信息的更新频率) 高度依赖于应用程序。SessionDetails |
查找特定用户的会话
现在,我们可以找到特定用户的所有会话。 以下示例显示了如何执行此操作:
@Autowired
FindByIndexNameSessionRepository<? extends Session> sessions;
@RequestMapping("/")
public String index(Principal principal, Model model) {
Collection<? extends Session> usersSessions = this.sessions.findByPrincipalName(principal.getName()).values();
model.addAttribute("sessions", usersSessions);
return "index";
}
在我们的实例中,我们查找当前登录用户的所有会话。 但是,您可以修改此设置,以便管理员使用表单指定要查找的用户。
findbyusername
示例应用程序
本节介绍如何使用示例应用程序。findbyusername
运行示例应用程序findbyusername
您可以通过获取源码并调用以下命令来运行该示例:
$ ./gradlew :spring-session-sample-boot-findbyusername:bootRun
要使该示例正常工作,您必须在 localhost 上安装 Redis 2.8+,并使用默认端口 (6379) 运行它。
或者,您也可以将 to 更新为 指向 Redis 服务器。
另一种选择是使用 Docker 在本地主机上运行 Redis。
有关详细说明,请参阅 Docker Redis 存储库。RedisConnectionFactory |
您现在应该能够访问 localhost:8080/ 中的应用程序
探索安全性样本应用程序
您现在可以尝试使用该应用程序。输入以下内容以登录:
-
用户名 user
-
密码 密码
现在单击 Login 按钮。 您现在应该会看到一条消息,指示您已使用之前输入的用户登录。 您还应该看到当前登录用户的活动会话列表。
您可以通过执行以下操作来模拟我们在 About the Sample 部分中讨论的流程:
-
打开一个新的隐身窗口并导航到 localhost:8080/
-
输入以下内容以登录:
-
用户名 user
-
密码 密码
-
-
结束原始会话。
-
刷新原始窗口,并查看您已注销。