|
此版本仍在开发中,尚未被认为是稳定的。请使用最新的稳定版本 Spring Session 4.0.2! |
Spring Session - 按用户名查找
假设
该指南假设您已经通过使用内置的Redis配置支持将Spring Session添加到了您的应用程序中。 此外,该指南还假设您已将Spring Security应用到了您的应用程序。 不过,该指南具有一定的通用性,可以应用于任何技术,并且在稍后的指南中我们将讨论所需的最小更改。
| 如果需要了解如何将Spring Session添加到您的项目中,请参阅示例和指南列表。 |
关于示例
我们的示例使用此功能来无效用户的会话,该会话可能已被篡改。 考虑以下场景:
-
用户前往图书馆并对接应用程序进行身份验证。
-
用户回家了,意识到忘记注销了。
-
用户可以使用如位置、创建时间、最后访问时间等线索在图书馆登录和结束会话。
如果我们可以让用户从任何身份验证设备在图书馆中注销会话,那不是很棒吗? 这个示例演示了如何实现这一点。
使用FindByIndexNameSessionRepository
要按用户名查找用户,您必须首先选择一个实现了 FindByIndexNameSessionRepository 的 SessionRepository。
我们的示例应用程序假设 Redis 支持已设置好,因此我们可以直接使用。
映射用户名
FindByIndexNameSessionRepository 只能在开发人员指示 Spring Session 与哪个用户关联的情况下,通过用户名找到会话。
您可以通过确保带有名称 FindByUsernameSessionRepository.PRINCIPAL_NAME_INDEX_NAME 的 session 属性被填充有用户名来实现这一点。
通常来说,您可以在用户认证之后立即使用以下代码来实现:<br>
String username = "username";
this.session.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, username);
向会话添加额外数据
可以将额外的信息(例如,IP地址、浏览器、位置和其他详细信息)与会话关联起来。 这样做可以让用户更容易知道他们正在查看哪个会话。
要这样做,确定您想要使用的会话属性以及希望提供的信息。 然后创建一个作为会话属性添加的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);
}
}
我们获取所需的信息,然后将 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
对于样例要正常工作,您必须在本地主机上安装 Redis 2.8+ 并使用默认端口(6379)运行它。
或者,您可以更新 RedisConnectionFactory 指向一个 Redis 服务器。
另一个选项是使用 Docker 在本地主机上运行 Redis。
有关详细说明,请参阅 Docker Redis 仓库。 |
您应该能够通过以下地址访问应用:localhost:8080/
探索安全示例应用程序
您可以现在试用该应用程序。请输入以下内容进行登录:
-
用户名 user
-
密码 密码
现在点击 登录 按钮。 你应该会看到一条消息,表明你已使用之前输入的用户名成功登录。 你还应该能看到当前已登录用户的所有活跃会话列表。
您可以通过以下步骤模拟我们在关于示例部分讨论的流程:
-
打开一个新的无痕窗口,导航到 localhost:8080/
-
请输入以下内容进行登录:
-
用户名 user
-
密码 密码
-
-
结束原来的会话。
-
刷新原始窗口后,请查看是否已注销。