programing

활성 사용자의 User Details를 가져오는 방법

prostudy 2022. 6. 5. 17:47
반응형

활성 사용자의 User Details를 가져오는 방법

유저가 , 하고 있습니다.UserDetails★★★★

User activeUser = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
log.debug(activeUser.getSomeCustomField());

잘 먹히긴 하는데, 이런 경우라면 봄이 더 편하게 살 수 있을 것 같아요.'먹다'를 수 있는 요?UserDetails컨트롤러 또는 메서드에 자동 연결되어 있는지 확인합니다.

예를 들어 다음과 같습니다.

public ModelAndView someRequestHandler(Principal principal) { ... }

'아예'가 '아예'가 아니라 '아예'로 받는 게 아니라UsernamePasswordAuthenticationToken, 나는 그것을 얻었다.UserDetails대??

나는 우아한 해결책을 찾고 있다.좋은 생각 있어요?

프리암블:Spring-Security 3.2 이후 주석 기능이 향상되었습니다.@AuthenticationPrincipal를 참조해 주세요.Spring-Security > = 3.2 를2た 、 Spring - Security >

다음 경우:

  • 이전 버전의 Spring-Security를 사용합니다.
  • 로그인이나 ID 등의 정보를 사용하여 데이터베이스에서 커스텀 사용자 개체를 로드해야 합니다.
  • HandlerMethodArgumentResolver ★★★★★★★★★★★★★★★★★」WebArgumentResolver문제를 풀 도 있습니다.@AuthenticationPrincipal ★★★★★★★★★★★★★★★★★」AuthenticationPrincipalArgumentResolver은, ( 「」 「」 「」 「」)에하고 있기 때문입니다.HandlerMethodArgumentResolver)

후 계속 않으면 ""를 합니다.★★★★★★★★★★★★★★★★★,@AuthenticationPrincipalWinch( Winch( Winch)@AuthenticationPrincipal그리고 루카스 슈멜자이젠(답변).

(BTW: 제 답변은 좀 더 나이가 들었기 때문에 (2012년 1월) Lukas Schmelzeisen이 첫 번째로 등장한 것은@AuthenticationPrincipalSpring Security 3.2 。


그러면 컨트롤러에서 를 사용할 수 있습니다.

public ModelAndView someRequestHandler(Principal principal) {
   User activeUser = (User) ((Authentication) principal).getPrincipal();
   ...
}

한 번이라도 필요하시면 됩니다.그러나 컨트롤러에 인프라스트럭처의 상세 정보가 포함되어 있기 때문에 몇 배 이상 필요한 경우에는 일반적으로 프레임워크에 의해 숨겨져 있어야 합니다.

따라서 이러한 컨트롤러가 필요합니다.

public ModelAndView someRequestHandler(@ActiveUser User activeUser) {
   ...
}

따라서 구현만 하면 됩니다.방법이 있다.

Object resolveArgument(MethodParameter methodParameter,
                   NativeWebRequest webRequest)
                   throws Exception

파라미터하고, 「Web」( 「Web」)을 가 있습니다.Usermethod 인수(첫 번째 파라미터)를 책임지고 있다고 생각되는 경우.

Spring 3.1 이후라고 불리는 새로운 개념이 있습니다.Spring 3.1+ 를 사용하고 있는 경우는, Spring 3.1+ 를 사용해 주세요(이 답변의 다음 항에 설명되어 있습니다).

public class CurrentUserWebArgumentResolver implements WebArgumentResolver{

   Object resolveArgument(MethodParameter methodParameter, NativeWebRequest webRequest) {
        if(methodParameter is for type User && methodParameter is annotated with @ActiveUser) {
           Principal principal = webRequest.getUserPrincipal();
           return (User) ((Authentication) principal).getPrincipal();
        } else {
           return WebArgumentResolver.UNRESOLVED;
        }
   }
}

사용자 지정 주석을 정의해야 합니다. - 모든 사용자 인스턴스를 항상 보안 컨텍스트에서 가져와야 하지만 명령 개체가 아닌 경우 주석을 건너뛸 수 있습니다.

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ActiveUser {}

구성에서는 다음 항목만 추가하면 됩니다.

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"
    id="applicationConversionService">
    <property name="customArgumentResolver">
        <bean class="CurrentUserWebArgumentResolver"/>
    </property>
</bean>

@ 참조: Spring MVC @Controller 메서드 인수를 커스터마이즈하는 방법을 학습합니다.

Spring 3.1을 사용하는 경우 WebArgumentResolver보다 HandlerMethodArgumentResolver를 권장합니다.Jay의 코멘트를 참조해 주세요.


도 마찬가지입니다.HandlerMethodArgumentResolver 3.1스프링 3.1+★

public class CurrentUserHandlerMethodArgumentResolver
                               implements HandlerMethodArgumentResolver {

     @Override
     public boolean supportsParameter(MethodParameter methodParameter) {
          return
              methodParameter.getParameterAnnotation(ActiveUser.class) != null
              && methodParameter.getParameterType().equals(User.class);
     }

     @Override
     public Object resolveArgument(MethodParameter methodParameter,
                         ModelAndViewContainer mavContainer,
                         NativeWebRequest webRequest,
                         WebDataBinderFactory binderFactory) throws Exception {

          if (this.supportsParameter(methodParameter)) {
              Principal principal = webRequest.getUserPrincipal();
              return (User) ((Authentication) principal).getPrincipal();
          } else {
              return WebArgumentResolver.UNRESOLVED;
          }
     }
}

구성에서 이 항목을 추가해야 합니다.

<mvc:annotation-driven>
      <mvc:argument-resolvers>
           <bean class="CurrentUserHandlerMethodArgumentResolver"/>         
      </mvc:argument-resolvers>
 </mvc:annotation-driven>

@'Spring MVC 3.1 HandlerMethodArgumentResolver 인터페이스 활용'을 참조하십시오.


스프링 보안 3.2 솔루션

Spring Security 3.2(Spring 3.2와 혼동하지 말 것)에는 자체 빌트인 솔루션이 있습니다.org.springframework.security.web.bind.annotation.AuthenticationPrincipal이는 루카스 슈멜자이젠의 답변에 잘 나타나 있다.

그냥 쓰는 거야

ModelAndView someRequestHandler(@AuthenticationPrincipal User activeUser) {
    ...
 }

, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , .AuthenticationPrincipalArgumentResolver )org.springframework.security.web.bind.support.AuthenticationPrincipalArgumentResolver : ": "" : "Activating" 중 @EnableWebMvcSecurity 이 을 는는에 mvc:argument-resolvers3.1 한 것과 으로 - 스프링 3.1 솔루션에서 설명했습니다.

@Spring Security 3.2 레퍼런스, 11.2장 "@AuthenticationPrincipal" 참조


Spring-Security 4.0 솔루션

.2 4.에서는 Spring 3.2가 합니다.@AuthenticationPrincipal ★★★★★★★★★★★★★★★★★」AuthenticationPrincipalArgumentResolver하다

(단, 오래된 패키지의 오래된 클래스는 아직 존재하므로 혼합하지 마십시오.)

그냥 쓰는 거야

import org.springframework.security.core.annotation.AuthenticationPrincipal;
ModelAndView someRequestHandler(@AuthenticationPrincipal User activeUser) {
    ...
}

하려면 , )을 해 둘 필요가 있습니다.org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver ": "activate" 에 @EnableWebMvcSecurity 이 을 는는에 mvc:argument-resolvers3.1 한 것과 으로 - 스프링 3.1 솔루션에서 설명했습니다.

<mvc:annotation-driven>
    <mvc:argument-resolvers>
        <bean class="org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver" />
    </mvc:argument-resolvers>
</mvc:annotation-driven>

@Spring Security 5.0 레퍼런스, 39.3장 @AuthenticationPrincipal 참조

Ralphs Answer는 우아한 솔루션을 제공하지만, Spring Security 3.2에서는 더 이상 자신의 솔루션을 구현할 필요가 없습니다.ArgumentResolver.

「 」가 UserDetails 행 implementCustomUser이치노

@RequestMapping("/messages/inbox")
public ModelAndView findMessagesForUser(@AuthenticationPrincipal CustomUser customUser) {

    // .. find messages for this User and return them...
}

Spring 보안 문서:@AuthenticationPrincipal을 참조하십시오.

스프링 되어 있기 MVC와는 Spring MVC를 합니다.스프링 보안은 다음을 반환합니다.AuthenticationHttpServletRequest.getUserPrincipal()디폴트로 메서드이기 때문에, 그것이 원금으로서 취득할 수 있는 것입니다. 해서 얻을 수 .UserDetails으로부터 이의를 제기하다

UserDetails ud = ((Authentication)principal).getPrincipal()

은 사용하는에 따라 수에 따라 수 ).UsernamePasswordAuthenticationToken )및 ('')Authentication밀히 a a를 포함할 는 없습니다.UserDetails 또는 수 . 이치노력하다

" " " 를 호출하고 SecurityContextHolder가장 우아한 접근법(이 방법을 따르겠습니다)은 고객의 요구와 사용자 객체 유형에 맞게 맞춤화된 자체 보안 컨텍스트액세서 인터페이스를 삽입하는 것입니다.관련 메서드를 사용하여 인터페이스를 만듭니다.을 사용하다

interface MySecurityAccessor {

    MyUserDetails getCurrentUser();

    // Other methods
}

다음 이 하려면 '하다'에 .SecurityContextHolder표준 구현에서는 코드를 스프링 보안에서 완전히 분리할 수 있습니다.그런 다음 보안 정보 또는 현재 사용자의 정보에 액세스해야 하는 컨트롤러에 이 정보를 삽입합니다.

또 다른 주요 이점은 테스트용 고정 데이터로 쉽게 구현할 수 있다는 것입니다. 스레드 로케이션을 채우는 등의 걱정은 없습니다.

「 」의 실장HandlerInterceptor 「」, 「」, 「」, 「」, 「」, 「」,UserDetails다음과 같이 모델이 있는 각 요청으로 이동합니다.

@Component 
public class UserInterceptor implements HandlerInterceptor {
    ....other methods not shown....
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        if(modelAndView != null){
            modelAndView.addObject("user", (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal());
        }
}

3.이 Spring Security 3.2 으로 즉시 할 수 .@AuthenticationPrincipal「」가 .AuthenticationPrincipalArgumentResolver.

그 용도의 간단한 예는 다음과 같습니다.

@Controller
public class MyController {
   @RequestMapping("/user/current/show")
   public String show(@AuthenticationPrincipal CustomUser customUser) {
        // do something with CustomUser
       return "view";
   }
}

는 Custom User에서 .authentication.getPrincipal()

AuthenticationPrincipalAuthenticationPrincipalArgumentResolver에 대응하는 Javadocs를 다음에 나타냅니다.

@Controller
public abstract class AbstractController {
    @ModelAttribute("loggedUser")
    public User getLoggedUser() {
        return (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    }
}

템플릿(예: JSP)에 권한이 있는 사용자가 필요한 경우

<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
<sec:authentication property="principal.yourCustomField"/>

와 함께

    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-taglibs</artifactId>
        <version>${spring-security.version}</version>
    </dependency>

다음과 같이 시험해 보십시오.[ Using Authentication Object from Spring ]를 사용하면 컨트롤러 방식에서 사용자 세부사항을 얻을 수 있습니다.다음 예에서는 인수와 함께 컨트롤러 방식으로 Authentication 객체를 전달하고 있습니다.사용자가 인증되면 Authentication Object에 세부 정보가 입력됩니다.

@GetMapping(value = "/mappingEndPoint") <ReturnType> methodName(Authentication auth) {
   String userName = auth.getName(); 
   return <ReturnType>;
}

를 취득하려면 , 「Active Users Details」를 합니다.@AuthenticationPrincipal과 같이 - 음음 in in in in in in in in in in in in in in 。

public String function(@AuthenticationPrincipal UserDetailsImpl user,
                    Model model){   
    model.addAttribute("username",user.getName()); //this user object 
contains user details 
    return "";
}

User Details Impl.java

import com.zoom.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;
import java.util.List;
public class UserDetailsImpl implements UserDetails {

@Autowired
private User user;

public UserDetailsImpl(User user) {
    this.user = user;
}

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
    SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority("ADMIN");
    return List.of(simpleGrantedAuthority);
}

@Override
public String getPassword() {
    return user.getPassword();
}

@Override
public String getUsername() {
    return user.getEmail();
}

@Override
public boolean isAccountNonExpired() {
    return true;
}

@Override
public boolean isAccountNonLocked() {
    return true;
}

@Override
public boolean isCredentialsNonExpired() {
    return true;
}

@Override
public boolean isEnabled() {
    return true;
}

public String getRole(){
    return user.getRole();
}

public String getName(){
    return user.getUsername();
}

public User getUser(){
    return user;
}
}

언급URL : https://stackoverflow.com/questions/8764545/how-to-get-active-users-userdetails

반응형