|
最新稳定版请使用Spring Session 3.5.3! |
春季课程 - 通过用户名查找
假设
本指南假设你已经通过 Redis 内置配置支持为应用添加了 Spring Session。 指南还假设你已经为申请应用应用了Spring Security。 不过,本指南较为通用,可以以最小改动应用于任何技术,相关内容我们稍后会讨论。
| 如果你需要学习如何将春季会话添加到你的项目中,请查看示例和指南列表 |
关于样本
我们的示例利用此功能使可能被攻破的用户会话失效。 请考虑以下情景:
-
用户进入库并向应用程序进行认证。
-
用户回家后才发现忘了登出。
-
用户可以通过地点、创建时间、最后访问时间等线索登录并从库结束会话。
如果我们能让用户在任何他们认证的设备上取消图书馆会话,那不是很好吗? 这个示例展示了这是可能的。
用FindByIndexNameSessionRepository
要通过用户名查找用户,首先必须选择一个会话仓库实现FindByIndexNameSessionRepository.
我们的示例应用假设 Redis 支持已经设置好,所以我们已经准备好了。
用户名映射
FindByIndexNameSessionRepository如果开发者指示 Spring Session 与会期.
你可以通过确保会话属性带有名称来实现FindByUsernameSessionRepository.PRINCIPAL_NAME_INDEX_NAME该用户名被填充。
一般来说,用户认证后,你可以立即使用以下代码进行:
String username = "username";
this.session.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, username);
向会话添加额外数据
为会话添加额外信息(如IP地址、浏览器、位置及其他细节)可能会很方便。 这样做让用户更容易知道自己正在看的是哪个会话。
为此,确定你想使用哪个会话属性以及你希望提供哪些信息。 然后创建一个 Java 豆,作为会话属性添加。 例如,我们的示例应用包含会话的位置和访问类型,如下列表所示:
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;
}
然后我们用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);
}
}
我们获取所需的信息,然后设置会议详情作为会期.
当我们取回会期通过用户名,我们可以利用会话访问会议详情就像我们对待其他会话属性一样。
你可能会好奇为什么春季课程不提供会议详情开箱即用的功能。
我们有两个原因。
第一个原因是应用程序自己实现这一点非常简单。
第二个原因是会话中填充的信息(以及这些信息更新的频率)高度依赖于应用程序。 |
为特定用户寻找会话
我们现在可以找到特定用户的所有会话。 以下示例展示了如何实现:
@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)运行。
或者,你也可以更新RedisConnection工厂指向一个Redis服务器。
另一个选择是用 Docker 在 localhost 上运行 Redis。
详见 Docker Redis 仓库中的详细说明。 |
你现在应该可以在localhost:8080/访问该应用了
探索安全示例应用
你现在可以尝试使用这个应用程序了。请输入以下方式登录:
-
用户名
-
密码密码
现在点击登录按钮。 你现在应该会看到一条消息,表示你已经登录了之前输入的用户。 你还应该会看到当前登录用户的活跃会话列表。
您可以通过以下作模拟我们在“关于样本”部分讨论的流程:
-
打开一个新的无痕窗口,导航到localhost:8080/
-
请输入以下方式登录:
-
用户名
-
密码密码
-
-
结束你的原始会话。
-
刷新原始窗口,看看你已经登出。