Spring Security 實戰干貨:如何獲取當前用戶信息
在某些場景中我們需要獲取當前的用戶是誰?如果你使用了Spring Secrity作為安全框架你可以通過以下手段獲取當前用戶。
SecurityContext
無論是有狀態的Session模式還是流行的JWT模式你都可以通過SecurityContext來獲取當前的用戶:
- Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
- String currentPrincipalName = authentication.getName();
當然這種方式是不夠嚴謹的,如果接口允許匿名訪問很可能返回一個匿名用戶,而匿名用戶并不能直接通過getName獲取,所以我們需要優化上面的邏輯為:
- Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
- if (!(authentication instanceof AnonymousAuthenticationToken)) {
- String currentUserName = authentication.getName();
- return currentUserName;
- }else{
- throw RuntimeException("No User")
- }
其實我平常使用這種方式的最多,我喜歡使用一個抽象的父類控制器來封裝獲取當前用戶的方法。
Principal
java.security.Principal對象也可以獲取當前的用戶信息,在Spring Security中該對象表現為Authentication對象,如果我們在Spring MVC接口中定義Principal對象也可以獲取當前用戶:
- @GetMapping("/currentusername")
- public String currentUserName(Principal principal) {
- return principal.getName();
- }
同理Authentication對象也是可以的:
- @GetMapping("/currentusername")
- public String currentUserName(Authentication authentication) {
- return authentication.getName();
- }
AuthenticationPrincipal
很多時候我們自定義了用戶對象UserDetails, 我們可以通過Spring Security 4.0提供的注解@AuthenticationPrincipal來獲取當前用戶的自定義UserDetails對象。如果CustomUser是UserDetails的實現,那么我們可以:
- @GetMapping("/currentusername")
- public String currentUserName(@AuthenticationPrincipal CustomUser customUser) {
- return customUser.getUsername();
- }
更簡單點的話:
- @GetMapping("/currentusername")
- public String currentUserName(@AuthenticationPrincipal(expression = "username") String username) {
- return username;
- }
這需要CustomUser包含一個getUsername方法。
甚至我們自定義一個注解也是可以的:
- @Target({ElementType.PARAMETER, ElementType.TYPE})
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- @AuthenticationPrincipal
- public @interface CurrentUser {}
CurrentSecurityContext
Spring Security 5 提供了一個新的注解@CurrentSecurityContext來獲取當前用戶的安全上下文,你可以:
- @GetMapping("/currentusername")
- public String currentUserName(@CurrentSecurityContext(expression = "authentication")
- Authentication authentication) {
- return authentication.getName();
- }
當然你還可以通過expression參數聲明SpEL表達式來獲取其它屬性,例如獲取Principal對象:
- @GetMapping("/principal")
- public String getPrincipal(@CurrentSecurityContext(expression = "authentication.principal")
- Principal principal) {
- return principal.getName();
- }
HttpServletRequest
據說HttpServletRequest的getUserPrincipal()方法也可以,但是我沒有用過,感興趣的同學可以試試能不能在Spring Security框架中直接通過該方法獲取。
總結
今天總結了如何在Spring Security獲取當前用戶的各種方法,它們的各自場景都略有不同,你可以根據這些羅列選擇最適合你的應用場景。
本文轉載自微信公眾號「碼農小胖哥」,可以通過以下二維碼關注。轉載本文請聯系碼農小胖哥公眾號。