복붙노트

[SPRING] 스프링 보안 @AuthenticationPrincipal

SPRING

스프링 보안 @AuthenticationPrincipal

@AuthenticationPrincipal을 사용자 정의 사용자 클래스에서 제대로 작동 시키려고 노력했습니다. 불행히도 사용자는 항상 null입니다. 코드는 다음과 같습니다.

제어 장치

@RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView index(@AuthenticationPrincipal User user) {
    ModelAndView mav= new ModelAndView("/web/index");
    mav.addObject("user", user);
    return mav;
}

보안 구성

@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    CustomUserDetailsService customUserDetailsService;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());
    }

}

CustomUserDetailsService

@Component
public class CustomUserDetailsService implements UserDetailsService {

@Autowired
UserRepository userRepository;

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    // Spring Data findByXY function
    return userRepository.findByUsername(username);
}

사용자 개체

public class User implements UserDetails{
    private String username;
    private String password;
    private Collection<Authority> authorities;

    // Getters and Setters

}

Authority Entity

public class Authority implements GrantedAuthority{
    private User user;
    private String role;

    // Getters and Setters

    @Override
    public String getAuthority() {
        return this.getRole();
    }
}

온라인에서 찾은 다양한 솔루션을 사용해 보았습니다. 내 사용자 정의 사용자 개체를 다음과 같이 변환 :

return new org.springframework.security.core.userdetails.User(user.getLogin(), user.getPassword(), true, true, true, true,  authorities);

액티브 사용자를 얻는 다른 방법은 문제없이 작동하지만 @AuthenticationProvider CustomUserObject가 가장 깨끗한 방법이라는 것을 알았습니다. 그래서이 기능을 사용하고 싶습니다. 어떤 도움이라도 대단히 감사합니다.

해결법

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

    1.@AuthenticationPrincipal을 사용하는 대신 메서드 인수에 인증 된 사용자에 대한 종속성을 직접 지정할 수 있습니다. 아래에 주어진 것

    @AuthenticationPrincipal을 사용하는 대신 메서드 인수에 인증 된 사용자에 대한 종속성을 직접 지정할 수 있습니다. 아래에 주어진 것

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public ModelAndView index(Principal user) {
        ModelAndView mav= new ModelAndView("/web/index");
        mav.addObject("user", user);
        return mav;
    } 
    

    이 Principal 객체는 Spring 보안을 통해 인증 된 실제 객체입니다. 메소드가 호출 될 때 Spring에서 이것을 삽입 할 것이다.

  2. ==============================

    2.

    @RequestMapping(method= RequestMethod.GET,value="/authenticate", produces = MediaType.APPLICATION_JSON_VALUE)
    public Object authenticate(@AuthenticationPrincipal Object obj) {
        return obj;
    }
    

    나는 똑같은 문제가있어, 나는이 일을 할 수 있었다. 당신은 매퍼와 함께 사용할 수 있습니다.

    @RequestMapping(method = RequestMethod.GET, value = "/authenticate2", produces = MediaType.APPLICATION_JSON_VALUE)
    public User authenticate2(@AuthenticationPrincipal Object obj) throws IOException {
        return mapper.readValue(mapper.writeValueAsString(obj), User.class);
    }
    

    이것들은 나를 위해 일했고, 미래에 누구에게나 도움이되기를 바랍니다.

  3. ==============================

    3.필자의 경우 UserDetails 객체가 아닌 String back (사용자 이름)을 얻습니다. 즉, 메소드 서명을 다음과 같이 정의해야합니다.

    필자의 경우 UserDetails 객체가 아닌 String back (사용자 이름)을 얻습니다. 즉, 메소드 서명을 다음과 같이 정의해야합니다.

    public ModelAndView index(@AuthenticationPrincipal String username)
    

    @AuthenticationPrincipal이 사실상 Authentication.getPrincipal ()을 반환하고 문서에 따라 이상한 것은 아닙니다.

    그래서, 귀하의 AuthenticationManager 구현은 단지 사용자 이름을 반환한다고 가정합니다.

  4. ==============================

    4.다른 해결책을 찾았습니다. 심지어 표준적인 것이 아닙니다.

    다른 해결책을 찾았습니다. 심지어 표준적인 것이 아닙니다.

    귀하의 컨트롤러에서

    @RequestMapping(value = "/login", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public ResponseEntity<UserDTO> login(@RequestBody UserDTO user){
        try {
            usersService.authenticate(user.getUsername(), user.getPassword());
            return new ResponseEntity<UserDTO>(user, HttpStatus.OK);
        }
        catch (BadCredentialsException e){
            return new ResponseEntity<UserDTO>(HttpStatus.UNAUTHORIZED);
        }
    }
    

    UserDTO가 사용자 이름과 암호를 포함하는 양식 일 경우

    CustomUserDetailsService에서

    public void authenticate(String username, String password){
        try{
            User user = new User(username, password);
            Authentication request = new UsernamePasswordAuthenticationToken(user, password, Arrays.asList(WebSecurityConfiguration.USER));
            Authentication result = authenticationManager.authenticate(request);
            SecurityContextHolder.getContext().setAuthentication(result);       
        } catch (InternalAuthenticationServiceException e){
            // treat as a bad credential
        }
    }
    

    고유의 AuthenticationManager 구현

    @Component
    class DefaultAuthenticationManager implements AuthenticationManager {
    
    @Autowired
    private CustomUserDetailsService usersService;
    
    public Authentication authenticate(Authentication auth) throws AuthenticationException {
        UserDetails user = usersService.loadUserByUsername(((User)auth.getPrincipal()).getUsername());
        if (user != null) {
            return new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities());
        }
    // Handle bad credentials here  
    }
    }
    

    근본적인 것은 CustomUserDetailsService # authenticate의 Principal이 인증 된 사용자의 이름이 아니라 객체이므로 프레임 워크에서 처리하고 @AuthenticationPrincipal 메커니즘을 통해 주입 할 수 있도록하는 것입니다. 이것은 나를 위해 일했습니다.

  5. ==============================

    5.나는 너와 똑같은 문제에 직면 해있다. 어떤 이유로 스프링 보안 @EnableWebSecurity가 argumentResolver를 자동으로 추가하지 않으므로 수동으로 추가해야합니다.

    나는 너와 똑같은 문제에 직면 해있다. 어떤 이유로 스프링 보안 @EnableWebSecurity가 argumentResolver를 자동으로 추가하지 않으므로 수동으로 추가해야합니다.

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

    6.@AuthenticationPrincipal 주석의 올바른 버전과 올바른 버전의 AuthenticationPrincipalArgumentResolver 클래스를 함께 사용하고 있는지 확인해야합니다.

    @AuthenticationPrincipal 주석의 올바른 버전과 올바른 버전의 AuthenticationPrincipalArgumentResolver 클래스를 함께 사용하고 있는지 확인해야합니다.

    4.0 버전의 Spring Security 이전 버전에서는 클래스를 사용해야했습니다.

    버전 4.0 이상에서는 다음을 사용해야합니다.

    구성 예제는 @AuthenticationPrincipal 공식 문서를 참조하십시오.

  7. from https://stackoverflow.com/questions/33616386/spring-security-authenticationprincipal by cc-by-sa and MIT license