복붙노트

[SPRING] Spring 보안은 UserDetails 객체를 반환하지 않으며, 사용자 이름 만 반환합니다.

SPRING

Spring 보안은 UserDetails 객체를 반환하지 않으며, 사용자 이름 만 반환합니다.

내 권한 구현이 완료되었다고 생각했지만 UserDetails 객체를 검색하려고 시도 할 때 사용자 이름이 모두 표시됩니다.

나는 다음과 같은 세부 사항으로 oauth를 사용하고있다.

AuthenticationManager 구성 :

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}

이렇게하면 내 userDetailsService로 디버깅 할 수 있습니다.

@Service
public class UserServiceImpl implements UserService, UserDetailsService {
@Override
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
        MyUser persistedUser = userRepository.findByEmail(email);

        if (persistedUser == null) {
            throw new UsernameNotFoundException(String.format("The email %s doesn't exist", email));
        }

        List<GrantedAuthority> authorities = new ArrayList<>();

        MyUser inMemoryUser = new MyUser(persistedUser.getEmail(), null, persistedUser.getEnabled(), false,
                false, false, authorities);

        return inMemoryUser;
    }
}

이것으로 정상적으로 끝나고 내 의뢰인은 JWT를 돌려 받게됩니다. 하지만 나중에 컨트롤러 메서드를 디버깅 할 때 다음과 같은 문제점을 발견했습니다.

@GetMapping
public @ResponseBody Iterable<Curriculum> getMyCurriculums(@AuthenticationPrincipal MyUser injectedUser) {
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    MyUser principle = (MyUser) auth.getPrincipal();
    return curriculumService.findByUser(principle);
}

이 경우, injectedUser = null, auth는 OAuth2Authentication이며 원칙은 사용자 이름 인 String입니다. MyUser 여야합니다.

해결법

  1. ==============================

    1.jwt 토큰을 MyUser 객체로 디코딩하도록 Spring Security를 ​​설정해야한다.

    jwt 토큰을 MyUser 객체로 디코딩하도록 Spring Security를 ​​설정해야한다.

    먼저 사용자 정의 OAuth2Authentication을 정의하여 MyUser를 캡슐화하십시오.

    public class OAuth2AuthenticationUser extends OAuth2Authentication {
    
        private MyUser myUser;
    
        public OAuth2AuthenticationUser(OAuth2Request storedRequest, Authentication userAuthentication) {
            super(storedRequest, userAuthentication);
        }
    
        public MyUser getMyUser() {
            return myUser;
        }
    
        public void setMyUser(MyUser) {
            this.myUser= myUser;
        }
    }
    

    그런 다음 보안 구성 클래스에서 다음과 같이 jwt 토큰 디코딩을 구성합니다.

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey("SIGNING_KEY");
        converter.setAccessTokenConverter(getAuthenticationAccessTokenConverter());
        return converter;
    }
    
    private DefaultAccessTokenConverter getAuthenticationAccessTokenConverter() {
        return new DefaultAccessTokenConverter() {
            @Override
            public OAuth2Authentication extractAuthentication(Map<String, ?> map) {
                OAuth2Authentication authentication = (OAuth2Authentication) super.extractAuthentication(map);
    
                OAuth2AuthenticationUser authenticationUser =
                        new OAuth2AuthenticationUser(authentication.getOAuth2Request(), authentication.getUserAuthentication());
    
                MyUser myUser = new MyUser();
    
                // Example properties
                myUser.setId(map.get("id") != null ? Long.valueOf(map.get("id").toString()) : null);
                myUser.setUsername(map.get("user_name") != null ? map.get("user_name").toString() : null);
                myUser.setFullName(map.get("fullName") != null ? map.get("fullName").toString() : null);
                myUser.setCustomerId(map.get("customerId") != null ? Long.valueOf(map.get("customerId").toString()) : null);
                myUser.setCustomerName(map.get("customerName") != null ? map.get("customerName").toString() : null);
    
                // More other properties
    
                authenticationUser.setMyUser(myUser);
    
                return authenticationUser;
            }
        };
    }
    

    그리고 다음과 같이 스프링 보안 컨텍스트에서 MyUser 객체에 액세스 할 수 있습니다.

    private static MyUser getMyUser() {
        OAuth2AuthenticationUser authentication = (OAuth2AuthenticationUser) SecurityContextHolder.getContext().getAuthentication();
        return (authentication != null && authentication.getMyUser() != null ? authentication.getMyUser() : new MyUser());
    }
    

    이것은 사용자 정보에 대한 데이터베이스 액세스가 최소화되고 jwt 토큰 만 있으면 stateless 환경에 적합합니다.

  2. from https://stackoverflow.com/questions/47805115/spring-security-not-returning-userdetails-object-only-username by cc-by-sa and MIT license