登录用户信息获取
在传统项目中进行用户登录处理时,通常会查询用户是否存在,如果存在就登录成功,同时将当前用户放在Session中。前面的案例中,使用整合Security进行用户授权管理后并没有显示的配置登录后的用户处理,那么这种情况下登录后的用户存放在哪里呢?存储的用户数据及结构又是怎样的呢?下面,通过HttpSession和SecurityContextHolder两种方式来获取登录后的用户信息。
1.使用HttpSession获取用户信息
为了简化操作,在之前创建的FilmeController控制类中新增一个用于获取当前会话用户信息的getUser()方法,示例代码如下。
@GetMapping("/getuserBySession")
@ResponseBody
public void getUser(HttpSession session) {
// 从当前HttpSession获取绑定到此会话的所有对象的名称
Enumeration<String> names = session.getAttributeNames();
while (names.hasMoreElements()){
// 获取HttpSession中会话名称
String element = names.nextElement();
// 获取HttpSession中的应用上下文
SecurityContextImpl attribute =
(SecurityContextImpl) session.getAttribute(element);
System.out.println("element: "+element);
System.out.println("attribute: "+attribute);
// 获取用户相关信息
Authentication authentication = attribute.getAuthentication();
UserDetails principal = (UserDetails)authentication.getPrincipal();
System.out.println(principal);
System.out.println("username: "+principal.getUsername());
}
}
上述代码中,在getUser(HttpSession session)方法中通过获取当前HttpSession的相关方法遍历并获取了会话中的用户信息。其中,通过getAttribute(element)获取会话对象时,默认返回的是一个Object对象,其本质是一个SecurityContextImpl类,为了方便查看对象数据,所以强制转换为SecurityContextImpl;在获取认证用户信息时,使用了Authentication的getPrincipal()方法,默认返回的也是一个Object对象,其本质是封装用户信息的UserDetails封装类,其中包括有用户名、密码、权限、是否过期等。
以Debug模式重启chapter07项目进行效果测试,项目启动成功后,通过浏览器访问“http://localhost:8080/
”项目首页,随意查看一个影片详情进行用户登录。用户登录成功后,在保证当前浏览器未关闭的情况下,使用同一浏览器执行“http://localhost:8080/getuserBySession
”来获取用户详情,效果如图1所示。
图1 访问项目首页效果
从图1可以看出,当前HttpSession会话中只有一个key为“SPRING_SECURITY_CONTEXT”的用户信息,并且用户信息被封装在SecurityContextImpl类对象中。另外,通过SecurityContextImpl类的相关方法可以进一步获取到当前登录用户的更多信息,其中关于用户的主要信息(例如用户名、用户权限等)都封装在UserDetails类中。
2.使用SecurityContextHolder获取用户信息
Spring Security针对于拦截的登录用户专门提供了一个SecurityContextHolder类,来获取Spring Security的应用上下文SecurityContex,进而获取封装的用户信息。下面,通过Security提供的SecurityContextHolder类来获取登录的用户信息。
在FilmeController控制类中新增一个获取当前会话用户信息的getUser2()方法,示例代码如下。
@GetMapping("/getuserByContext")
@ResponseBody
public void getUser2() {
// 获取应用上下文
SecurityContext context = SecurityContextHolder.getContext();
System.out.println("userDetails: "+context);
// 获取用户相关信息
Authentication authentication = context.getAuthentication();
UserDetails principal = (UserDetails)authentication.getPrincipal();
System.out.println(principal);
System.out.println("username: "+principal.getUsername());
}
上述代码中,通过Security提供的SecurityContextHolder类先获取了应用上下文对象SecurityContext,并通过其相关方法获取了当前登录用户信息。通过与HttpSession方式获取用户信息的示例对比可以发现,这两种方法的本质就是获取SecurityContext的不同,其他后续方法基本一致。
至此,关于Spring Boot整合Spring Security拦截后的登录用户信息获取就已经讲解完毕了。这里介绍的两种方法中,HttpSession的方式获取用户信息相对比较传统,而且必须引入HttpSession对象;而Security提供的SecurityContextHolder则相对简便,也是在Security项目中相对推荐的使用方式。