스프링 보안에서 현재 로그인한 사용자 개체를 가져오는 방법은 무엇입니까?
Spring 보안 버전 3.1.4를 사용하고 있습니다.풀어주다.현재 로그인한 사용자 개체에 액세스하려면 어떻게 해야 합니까?
SecurityContextHolder.getContext().getAuthentication().getPrincipal()
사용자 개체가 아닌 사용자 이름을 반환합니다.그러면 반환된 사용자 이름을 사용하고 UserDetails 개체를 가져오려면 어떻게 해야 합니까?
다음 코드를 사용해 보았습니다.
public UserDetails getLoggedInUser(){
final Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null && auth.isAuthenticated() && !(auth instanceof AnonymousAuthenticationToken))
{
if(auth.getDetails() !=null)
System.out.println(auth.getDetails().getClass());
if( auth.getDetails() instanceof UserDetails)
{
System.out.println("UserDetails");
}
else
{
System.out.println("!UserDetails");
}
}
return null;
}
결과는 다음과 같습니다.
[2015-08-17 19:44:46.738] INFO http-bio-8443-exec-423 System.out class org.springframework.security.web.authentication.WebAuthenticationDetails
[2015-08-17 19:44:46.738] INFO http-bio-8443-exec-423 System.out !UserDetails
AuthenticationFilter 클래스는 다음과 같습니다.
public class CustomUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "j_username";
public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "j_password";
public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME";
private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
private boolean postOnly = true;
public CustomUsernamePasswordAuthenticationFilter() {
super("/j_spring_security_check");
}
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
String username = obtainUsername(request);
String password = obtainPassword(request);
if (username == null) {
username = "";
}
if (password == null) {
password = "";
}
username = username.trim();
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
// Allow subclasses to set the "details" property
setDetails(request, authRequest);
if(this.getAuthenticationManager()==null){
logger.info("Authentication manager is null.");
} else {
logger.info("Authentication manager was "+this.getAuthenticationManager().getClass().getName());
}
return this.getAuthenticationManager().authenticate(authRequest);
}
protected String obtainPassword(HttpServletRequest request) {
return request.getParameter(passwordParameter);
}
protected String obtainUsername(HttpServletRequest request) {
return request.getParameter(usernameParameter);
}
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
}
public void setUsernameParameter(String usernameParameter) {
this.usernameParameter = usernameParameter;
}
public void setPasswordParameter(String passwordParameter) {
this.passwordParameter = passwordParameter;
}
public void setPostOnly(boolean postOnly) {
this.postOnly = postOnly;
}
public final String getUsernameParameter() {
return usernameParameter;
}
public final String getPasswordParameter() {
return passwordParameter;
}
}
인증 공급자는 다음과 같습니다.
@Component
public class CustomAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
private MyUserDetailsService userDetailsService;
public MyUserDetailsService getUserDetailsService() {
return userDetailsService;
}
public void setUserDetailsService(MyUserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
@Override
protected void additionalAuthenticationChecks(UserDetails arg0,
UsernamePasswordAuthenticationToken arg1)
throws AuthenticationException {
}
@Override
protected UserDetails retrieveUser(String arg0,
UsernamePasswordAuthenticationToken arg1)
throws AuthenticationException {
return userDetailsService.loadUserByUsername(arg0);
}
}
UserDetails 클래스는 다음과 같습니다.
public class MyUserDetailsService implements UserDetailsService {
private final Map<String, UserDetails> usersList;
public MyUserDetailsService() {
Collection<GrantedAuthority> authorityList;
final SimpleGrantedAuthority supervisorAuthority = new SimpleGrantedAuthority("supervisor");
final SimpleGrantedAuthority userAuthority = new SimpleGrantedAuthority("user");
usersList = new TreeMap<String, UserDetails>();
authorityList = new ArrayList<GrantedAuthority>();
authorityList.add(supervisorAuthority);
authorityList.add(userAuthority);
usersList.put("admin", new User("admin", "admin", authorityList));
authorityList = new ArrayList<GrantedAuthority>();
authorityList.add(userAuthority);
usersList.put("peter", new User("peter", "password123", authorityList));
//probably don't use this in production
for(Map.Entry<String, UserDetails> user : usersList.entrySet()){
logger.info(user.getValue().toString());
}
}
@Override
public UserDetails loadUserByUsername(String username)throws UsernameNotFoundException {
UserDetails ud = usersList.get(username);
if (ud != null) {
logger.info("loadUserByUsername: found match, returning "
+ ud.getUsername() + ":" + ud.getPassword() + ":"
+ ud.getAuthorities().toString());
return new User(ud.getUsername(), ud.getPassword(),
ud.getAuthorities());
}
logger.info("loadUserByUsername: did not find match, throwing UsernameNotFoundException");
throw new UsernameNotFoundException(username);
}
}
SecurityContextHolder.getContext().getAuthentication().getPrincipal();
현재 사용자 개체를 반환합니다.이것은 가능합니다.User
,UserDetails
또는 사용자 지정 사용자 개체입니다.반환 개체를 다음으로 캐스팅해야 합니다.UserDetails
또는 사용자 지정 개체인 경우 사용자 개체입니다.
또는 주사할 수 있습니다.Authentication
또는Principal
컨트롤러에 직접 연결됩니다.원칙은 당신의 것입니다.UserDetails
/custom 사용자 개체입니다.
참고:UserDetails
인터페이스입니다.
당신은 그것을 사용할 수 있습니다.
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof UserDetails) {
String username = ((UserDetails)principal).getUsername();
} else {
String username = principal.toString();
}
그것은 봄 보안 참조 http://docs.spring.io/spring-security/site/docs/4.0.2.RELEASE/reference/htmlsingle/ # 현재 사용자에 대한 정보입니다.
아래와 같이 컨트롤러에 인증 인터페이스를 주입하고 로그인한 사용자의 사용자 이름을 가져올 수 있습니다.
@GetMapping(value = "/username")
@ResponseBody
public String currentUserName(Authentication authentication) {
if (authentication != null)
return authentication.getName();
else
return "";
}
당신은 방금 한 발짝 더 나갔습니다.SecurityContextHolder.getContext().getAuthentication()
반환합니다.Authentication
물건.어떻게 사용자를 인증했는지, 그리고 구체적인 클래스가 구현할 수 있는 것은 무엇인지 알아야 합니다.Authentication
의 하위 클래스라고 가정합니다.AbstractAuthenticationToken
(제공되는 모든 봄 구현은 다음과 같습니다.)getDetails()
를 반환합니다.UserDetails
다음을 사용할 수 있습니다.
AbstractAuthenticationToken auth = (AbstractAuthenticationToken)
SecurityContextHolder.getContext().getAuthentication();
UserDetails details = (UserDetails) auth.getDetails();
저는 이 문제를 사용하여 해결했습니다.SecurityContextHolder
그리고.Authentication.getName()
:
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String login = authentication.getName();
User user = usersService.getUserByLogin(login);
버전 5.2부터는 CurrentSecurityContext 주석을 사용하여 현재 사용자 인증을 받을 수 있습니다.
@GetMapping("/authentication")
public Object authentication(@CurrentSecurityContext(expression="authentication")
Authentication authentication) {
return authentication.getDetails();
}
또는 심지어:
@GetMapping("/hello")
public String hello(@CurrentSecurityContext(expression="authentication.name")
String username) {
return "Hello, " + username + "!";
}
현재 사용자의 모든 속성을 가져오려면 먼저 다음을 구현하는 클래스로 이동합니다.UserDetails
라고 불릴 가능성이 더 높습니다.UserPrincipal
각 속성에 대해 다음과 같은 get method를 작성합니다.getAge()
두번째로 HTML 파일로 가서 이것을 씁니다.
<span th:text="${#request.userPrincipal.principal.age}> </span>
그리고 컨트롤러에 ModelAttribute를 추가할 필요가 없습니다. 문제가 해결되기를 바라며, 저에게 물어볼 수 있습니다.
다음을 통해 현재 로그인 사용자를 얻을 수 있습니다.
@Authenticationprincipal
SecurityContextHolder.getContext().getAuthentication().getPrinciple()
구현된 클래스로 주체를 다운캐스트해야 합니다. 그런 다음 securityContext에서 설정한 컨텍스트 개체를 추출할 수 있습니다.
AbstractAuthenticationToken a = (AbstractAuthenticationToken) request.getUserPrincipal();
UserContext context = (UserContext) a.getPrincipal();
이 솔루션은 Spring Boot 2.5에서 작동했습니다.
먼저, 다음을 정의합니다.User
Principal
학급
public class UserPrincipal implements UserDetails {
private static final long serialVersionUID = 1L;
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
// other methods ....
}
둘째, 다음을 정의합니다.User
명령어:
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
String username;
String password;
//getters ans setters ...
}
셋째, 다음을 정의합니다.UserAuth
명령어:
public class UserAuth {
public String getUsername()
{
UserPrincipal principal
= (UserPrincipal)SecurityContextHolder
.getContext()
.getAuthentication()
.getPrincipal();
return principal.getUser().getUsername();
}
}
마지막으로, 당신은 자동 배선할 수 있습니다.UserAuth
필요에 따라 수업합니다.
public class User implements UserDetails {
private String firstname;
private String lastname;
}
사용자 정의 사용자가 UserDetails 클래스를 구현하고 있다고 가정합니다.
@RestController
@RequestMapping("/api/user")
class UsersController {
@GetMapping
public User fetchUser(@AuthenticationPrincipal User user) {
return user;
}
}
그래서 거의 모든 대답이 올바르고 실현 가능해 보입니다. 모든 기여자들에게 칭찬이지만 상용판 코드를 제거하는 것은 유용하고 쉬울 수 있습니다. 모든 유틸리티 방법을 포함하는 인터페이스와 그 구현을 만들고, 그 다음에는 간단하게 만들 수 있습니다.@Autowire
거그거.
public interface AuthHelper {
Authentication getAuthentication();
public String getName();
public UserDetails getUserDetails()
}
@Component
public class AuthHelperImpl implements AuthHelper {
@Override
public Authentication getAuthentication() {
return SecurityContextHolder.getContext().getAuthentication();
}
public String getName() {
return getAuthentication().getName();
}
public UserDetails getUserDetails() {
return (UserDetails) getAuthentication().getPrincipal();
}
//and more utilities you need
//you can also cast with UserPrincipal
}
이제 컨트롤러에서:
@Controller
public class DemoController {
@Autowired
private AuthHelper authHelper;
@RequestMapping(value = "/username", method = RequestMethod.GET)
@ResponseBody
public String currentUserNameSimple() {
return authHelper.getName;
}
}
이것은 읽기에 좋은 기사일 수 있습니다.이 문서에서는 스프링 응용 프로그램에서 사용자 정보를 가져오는 방법을 공통 정적 액세스 메커니즘에서 시작하여 주체를 주입하는 몇 가지 더 나은 방법을 보여 줍니다.
https://www.baeldung.com/get-user-in-spring-security
언급URL : https://stackoverflow.com/questions/32052076/how-to-get-the-current-logged-in-user-object-from-spring-security
'programing' 카테고리의 다른 글
Oracle 캐스케이드 삭제 (0) | 2023.07.25 |
---|---|
페이지화 쿼리에서 ROWNUM은 어떻게 작동합니까? (0) | 2023.07.25 |
마리아드브:MySQL 서버가 사라졌습니다. (0) | 2023.07.25 |
ADO.NET에서 Oracle을 호출할 때 여러 개의 선택 문 배치 (0) | 2023.07.20 |
ORA-01799: 열을 하위 쿼리에 외부 결합할 수 없습니다. (0) | 2023.07.20 |