此版本仍在开发中,尚未被认为是稳定的。请使用最新的稳定版本 Spring Session 4.0.2spring-doc.cadn.net.cn

Spring Session - 按用户名查找

此指南描述了如何使用 Spring Session 按用户名查找会话的方法。spring-doc.cadn.net.cn

您可以在findbyusername 应用程序中找到完成的指南。

假设

该指南假设您已经通过使用内置的Redis配置支持将Spring Session添加到了您的应用程序中。 此外,该指南还假设您已将Spring Security应用到了您的应用程序。 不过,该指南具有一定的通用性,可以应用于任何技术,并且在稍后的指南中我们将讨论所需的最小更改。spring-doc.cadn.net.cn

如果需要了解如何将Spring Session添加到您的项目中,请参阅示例和指南列表

关于示例

我们的示例使用此功能来无效用户的会话,该会话可能已被篡改。 考虑以下场景:spring-doc.cadn.net.cn

如果我们可以让用户从任何身份验证设备在图书馆中注销会话,那不是很棒吗? 这个示例演示了如何实现这一点。spring-doc.cadn.net.cn

使用FindByIndexNameSessionRepository

要按用户名查找用户,您必须首先选择一个实现了 FindByIndexNameSessionRepositorySessionRepository。 我们的示例应用程序假设 Redis 支持已设置好,因此我们可以直接使用。spring-doc.cadn.net.cn

映射用户名

FindByIndexNameSessionRepository 只能在开发人员指示 Spring Session 与哪个用户关联的情况下,通过用户名找到会话。 您可以通过确保带有名称 FindByUsernameSessionRepository.PRINCIPAL_NAME_INDEX_NAME 的 session 属性被填充有用户名来实现这一点。spring-doc.cadn.net.cn

通常来说,您可以在用户认证之后立即使用以下代码来实现:<br>spring-doc.cadn.net.cn

String username = "username";
this.session.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, username);

使用 Spring Security 映射用户名

由于我们使用了Spring Security,用户名会自动进行索引。 这意味着我们无需执行任何步骤来确保用户名已被索引。spring-doc.cadn.net.cn

向会话添加额外数据

可以将额外的信息(例如,IP地址、浏览器、位置和其他详细信息)与会话关联起来。 这样做可以让用户更容易知道他们正在查看哪个会话。spring-doc.cadn.net.cn

要这样做,确定您想要使用的会话属性以及希望提供的信息。 然后创建一个作为会话属性添加的Java bean。 例如,在我们的示例应用程序中,包括了会话的位置和访问类型,如下所示:spring-doc.cadn.net.cn

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将这些信息注入会话,如下例所示:spring-doc.cadn.net.cn

@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-doc.cadn.net.cn

您可能想知道,为什么 Spring Session 不提供 SessionDetails 功能。 我们有两个原因。 第一个原因是应用程序自己实现这一点非常简单。 第二个原因是会话中填充的信息(以及这些信息更新的频率)高度依赖于应用程序。

查找特定用户的会话

我们现在可以找到特定用户的全部会话。 以下示例展示了如何实现这一点:spring-doc.cadn.net.cn

@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";
}

在我们的实例中,我们将找到当前已登录用户的所有会话。 但是,您可以通过表单指定管理员查找哪个用户。spring-doc.cadn.net.cn

findbyusername示例应用程序

此部分描述了如何使用findbyusername样本应用程序。spring-doc.cadn.net.cn

运行findbyusername示例应用程序

您可以运行示例程序,通过获取源代码并执行以下命令来实现:spring-doc.cadn.net.cn

$ ./gradlew :spring-session-sample-boot-findbyusername:bootRun
对于样例要正常工作,您必须在本地主机上安装 Redis 2.8+ 并使用默认端口(6379)运行它。 或者,您可以更新 RedisConnectionFactory 指向一个 Redis 服务器。 另一个选项是使用 Docker 在本地主机上运行 Redis。 有关详细说明,请参阅 Docker Redis 仓库

您应该能够通过以下地址访问应用:localhost:8080/spring-doc.cadn.net.cn

探索安全示例应用程序

您可以现在试用该应用程序。请输入以下内容进行登录:spring-doc.cadn.net.cn

现在点击 登录 按钮。 你应该会看到一条消息,表明你已使用之前输入的用户名成功登录。 你还应该能看到当前已登录用户的所有活跃会话列表。spring-doc.cadn.net.cn

您可以通过以下步骤模拟我们在关于示例部分讨论的流程:spring-doc.cadn.net.cn