SecurityContext и SecurityContextHolder являются двумя основными классами Spring Security. SecurityContext
используется для хранения сведений о текущем аутентифицированном пользователе, также известном как принцип. Итак, если вам нужно получить имя пользователя или любые другие данные пользователя, вам нужно сначала получить этот SecurityContext
. SecurityContextHolder
является вспомогательным классом, который обеспечивает доступ к контексту безопасности. По умолчанию он использует объект ThreadLocal для хранения контекста безопасности, что означает, что контекст безопасности всегда доступен для методов в одном и том же потоке выполнения, даже если вы не передаете объект SecurityContext. Не беспокойтесь об утечке памяти ThreadLocal в веб-приложении, хотя Spring Security позаботится об очистке ThreadLocal.
Кстати, это не единственный способ, когда SecurityContextHolder
может хранить текущий SecurityContext
, его можно настроить с помощью стратегии при запуске, чтобы указать, каким образом вы хотите сохранить контекст. Например, вы можете использовать стратегию SecurityContextHolder.MODE_GLOBAL
для автономного приложения.
Ключевым моментом, который необходимо изучить, является то, как вы получаете SecurityContext из SecurityContextHolder? а затем получить данные текущего пользователя из этого? Например, если вы хотите знать имя текущего пользователя, вошедшего в систему, то как вы получите его в Spring security?
Чтобы получить текущее имя пользователя, вам сначала необходим SecurityContext
, полученный из SecurityContextHolder
. Этот SecurityContext
хранит данные пользователя в объекте аутентификации, который можно получить, вызвав getAuthentication()
.
Как только вы получили объект аутентификации, вы можете либо привести его к UserDetails, либо использовать его как есть. Объект UserDetails используется Spring Security для хранения информации, связанной с пользователем.
Как получить текущий логин в Spring Security
Вот код для получения контекста безопасности в Spring Security и получения имени текущего пользователя, вошедшего в систему:
1
2
3
4
5
6
7
|
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); if (principal instanceof UserDetails) { String username = ((UserDetails)principal).getUsername(); } else { String username = principal.toString(); } |
Объект, возвращаемый getContext()
является экземпляром интерфейса SecurityContext
. Это объект, который хранится в локальном потоке.
Метод getPrincipal()
обычно возвращает объект UserDetails в Spring Security, который содержит все детали текущего пользователя, вошедшего в систему.
В любом случае, если вы посмотрите ближе, вы обнаружите, что это не очень хороший код, когда мы думаем о Spring и внедрении зависимостей . Поэтому, если вам когда-либо понадобится узнать текущие данные пользователя, вошедшего в систему, например, в контроллере Spring MVC, я предлагаю вам объявить зависимость и позволить Spring предоставить вам объект Principal
, а не запрашивать их и создавать тесно связанную систему.
Вот пример этого
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
import java.security.Principal; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; @Controller public class MVCController { @RequestMapping (value = "/username" , method = RequestMethod.GET) @ResponseBody public String currentUserName(Principal principal) { return principal.getName(); } } |
Кроме того, вы также можете запросить объект аутентификации вместо основного объекта, как показано ниже:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
import org.springframework.security.core.Authentication; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; @Controller public class SpringMVCController { @RequestMapping (value = "/username" , method = RequestMethod.GET) @ResponseBody public String currentUserName(Authentication authentication) { return authentication.getName(); } } |
Если вы хотите узнать больше способов, вы также можете увидеть мой пост о трех способах получения текущего имени пользователя в Spring Security , где я рассмотрел еще несколько способов получения текущего имени пользователя в контроллере Spring MVC.
Это все о том, что такое контекст безопасности в безопасности Spring и как вы можете получить SecurityContext из класса SecurityContextHolder. Это некоторые из основных классов, поэтому вы должны быть знакомы с ними.
Часть хранения, т.е. SecurityContext
хранится в ThreadLocal
является необязательной, но также полезно знать подробности. Просто помните, что если вам когда-либо понадобятся данные пользователя, например, имя пользователя и т. Д., Вам лучше запросить принципал или объект аутентификации в контроллере Spring MVC, а не использовать SecurityContextHolder
для их получения.
Спасибо за чтение этой статьи до сих пор. Если вам нравится этот учебник Spring Security, поделитесь им с друзьями и коллегами. Если у вас есть какие-либо вопросы или пожелания, напишите нам.
См. Оригинальную статью здесь: Что такое SecurityContext и SecurityContextHolder в Spring Security?
Мнения, высказанные участниками Java Code Geeks, являются их собственными. |