本教程将展示如何在Spring 安全性中检索用户详细信息。
当前经过身份验证的用户可以通过 Spring 中的多种不同机制使用。让我们先介绍最常见的解决方案 — 编程访问。
检索当前经过身份验证的主体的最简单方法是通过对SecurityContextHolder 的静态调用:
- Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
- String currentPrincipalName = authentication.getName();
对此代码段的改进是,在尝试访问它之前,首先检查是否存在经过身份验证的用户:
- Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
- if (!(authentication instanceof AnonymousAuthenticationToken)) {
- String currentUserName = authentication.getName();
- return currentUserName;
- }
当然,像这样的静态调用也有缺点,代码的可测试性降低是更明显的缺点之一。相反,我们将探索满足这一非常常见要求的替代解决方案。
我们在注释 bean 中还有其他选项@Controller。
我们可以直接将主体定义为方法参数,框架会正确解析:
- @Controller
- public class SecurityController {
- @RequestMapping(value = "/username", method = RequestMethod.GET)
- @ResponseBody
- public String currentUserName(Principal principal) {
- return principal.getName();
- }
- }
或者,我们也可以使用身份验证令牌:
- @Controller
- public class SecurityController {
- @RequestMapping(value = "/username", method = RequestMethod.GET)
- @ResponseBody
- public String currentUserName(Authentication authentication) {
- return authentication.getName();
- }
- }
身份验证类的 API 非常开放,因此框架尽可能保持灵活性。因此,Spring 安全性主体只能作为对象检索,并且需要强制转换为正确的UserDetails实例:
- UserDetails userDetails = (UserDetails) authentication.getPrincipal();
- System.out.println("User has authorities: " + userDetails.getAuthorities());
最后,这是直接来自HTTP请求:
- @Controller
- public class GetUserWithHTTPServletRequestController {
- @RequestMapping(value = "/username", method = RequestMethod.GET)
- @ResponseBody
- public String currentUserNameSimple(HttpServletRequest request) {
- Principal principal = request.getUserPrincipal();
- return principal.getName();
- }
- }
为了充分利用 Spring 依赖注入并能够在任何地方检索身份验证,而不仅仅是在 be@Controller 中,我们需要将静态访问隐藏在一个简单的外观后面:
- public interface IAuthenticationFacade {
- Authentication getAuthentication();
- }
- @Component
- public class AuthenticationFacade implements IAuthenticationFacade {
- @Override
- public Authentication getAuthentication() {
- return SecurityContextHolder.getContext().getAuthentication();
- }
- }
外观公开身份验证对象,同时隐藏静态状态并保持代码分离且完全可测试:
- @Controller
- public class GetUserWithCustomInterfaceController {
- @Autowired
- private IAuthenticationFacade authenticationFacade;
- @RequestMapping(value = "/username", method = RequestMethod.GET)
- @ResponseBody
- public String currentUserNameSimple() {
- Authentication authentication = authenticationFacade.getAuthentication();
- return authentication.getName();
- }
- }
通过利用 Spring Security Taglib 支持,也可以在JSP 页面中访问当前经过身份验证的主体。
首先,我们需要在页面中定义标签:
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>
接下来,我们可以参考委托人:
- authenticated as
Thymeleaf是一个现代化的服务器端Web模板引擎,与Spring MVC框架具有良好的集成。
让我们看看如何使用 Thymeleaf 引擎在页面中访问当前经过身份验证的主体。
首先,我们需要添加thymeleaf-spring5 和 thymeleaf-extras-springsecurity5依赖项,以将 Thymeleaf 与 Spring Security 集成:
-
org.thymeleaf.extras -
thymeleaf-extras-springsecurity5 -
org.thymeleaf -
thymeleaf-spring5
现在我们可以使用 sec:authorize 属性在 HTML 页面中引用主体:
- xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
-
- Authenticated as
本文展示了如何在 Spring 应用程序中获取用户信息,从常见的静态访问机制开始,然后是几种更好的注入主体的方法。
这些示例的实现可以在GitHub 项目中找到。这是一个基于 Eclipse 的项目,因此应该很容易导入和按原样运行。在本地运行项目时,我们可以在此处访问主页 HTML:
http://localhost:8080/spring-security-rest-custom/foos/1