진행하기전에 저번 포스팅에서 DB연결 과정을 한번 보고 가자
현재 클래스에서 DB 에서부터 현재 인증을 시도 하고 있는 사용자의 계정이 존재하는지 username 을 통해서 확인하고 확인되면 Account 객체를 얻을수 있다. (만약에 널이면 UsernameNotFoundException 으로 예외 처리되고 최종적으로 UserDeatails 타입으로 반환된다 .)
AccountContext 클래스를 통해서 Account 와 권한정보를전달해주는데 이 객체는 User클래스를 상속받는다 그리고 User는 UserDetails인터페이스를 구현하고 있다. 그리고 마지막엔 AccountContext가 리턴을 하게 된다.
여기 까지가 저번 포스팅 내용이다.
오늘은 반환된 반환되는 객체를 받아서 추가적인 검증을 진행하는 AuthenticationProvider를 직접 생성해서 인증처리가 되도록 해보겠다
AuthenticationProvider 인터페이스를 구현해보도록 하겠다
authenticate | supports |
검증을 위한 메소드 이고 | 현재 파라메터로 전달되는 클래스 타입과 CustomAuthenticationProvider 사용하고자 하는 토큰과 일치하면 인증처리 하도록 하는메소드 이다. |
저번 포스팅에서 내가 만든 UserDetailsService 가 필요하고 PasswordEncoder 까지 두개의 클래스가 필요하다
파라메터로 전달받는 // Authentication | AuthenticationManager로 부터 전달받는 인증객체다 사용자가 인증할때 사용자의 패스워드 정보가 들어가 있다. |
String userName = authentication.getName(); | 로그인할때 입력한 아이디 |
String passwrod = (String) authentication.getCredentials(); | 패스워드 참조 (오브젝트로 나오기때문에 String 으로 형변환) |
AccountContext accountContext = (AccountContext) userDetailsService.loadUserByUsername(userName); | userDetails 타입의 객체를 얻어 온다 최종적으로 AccountContext 타입으로 받아온다 |
if (!passwordEncoder.matches(passwrod,accountContext.getAccount().getPassword())){ } |
사용자가 입력한 비밀번호 , AccountContext에 저장된 비빌번호가 일치하는지 검증 |
throw new BadCredentialsException("비밀번호 오류 인증실패 "); | 일치 하지 않으면 예외 발생 |
현재는 입력한 비밀번호와 DB에 저장된 비밀번호가 일치한다 Provider 객체는 UsrenamePasswordAuthenticationToken 객체를 만든다
이전에 이 클래스의 생성자를 확인해보자
2개의 생성자를 확인해보면
첫번째 생성자는 사용자가 인증을 시도할때 인증필터가 이 생성자에게 사용자의 아이디와 패스워드를 담아서 AuthenticationManager에게 전달한다 즉 로그인 정보를 저장할때 사용한다
두번째 생성자는 인증에 성공한 이후에 할일을 두번째 생성자에게전달한다 권한정보와 인증에성공한 인증객체를 저장하는곳이다
principal | credentials |
사용하는 사용자 디바이스 혹은 시스템을 통칭한다 | 인증 과정 중, 주체가 본인을 인증하기 위해 서버에 제공하는 것. (ID, Password 같은 것) , 즉 증명서라고 보면된다. |
지금 현재는 로그인이 성공한 상태고 두번째 생성자에게 전달하고자 한다
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken (accountContext.getAccount(), null,accountContext.getAuthorities()); |
인증에 성공한 인증객체, 비밀번호(null), 권한정보 최종적으로 성공한 인증정보들을 객체로 만들어서 다시 provider를 호출한 AuthenticationManager에게 반환하게된다. |
이구문도 개발자가 설계할때 정책이나 요구되는 사항들을 다양하게 구성해서 사용할수 있다.
이번에 만든 클래스를 사용해야 하니 저번 포스팅에서 만들어 뒀던 SecurityConfigu에서 구현해보겠다.
auth.authenticationProvider(authenticationProvider()); | authenticationProvider bean 객체를 만들어서 전달하면된다. |
public AuthenticationProvider authenticationProvider() { return new CustomAuthenticationProvider(); } |
bean 객체이고 아까 내가 만든 클래스를 참조 할수 있도록 한다 |
이렇게 되면 springSecurity 직접 만든 클래스(CustomAuthenticationProvider)를 참조하게된다. 디버깅 해서 테스를 해보자
ProviderManager 가 어떻게 활용되는지 살펴볼것이다.
AuthenticationFilter 와 FORM 인증 필터를 받고서 ProviderManager 에게 다시 인증처리를 맡긴다 그때 authentication 인증객체 를 전달한다 인자값을 보면 확인할수 있다.
현재는 인증을 시도 하는 중이라서 익명사용자로 확인된다. 그리고 부모 provider를 가지고 있는데 확인해보면 아까전에 만들었던 CustomAuthenticationProvider가 확인된다. 그래서 부모 까지 탐색을 시도한다.
여기서 확인해보면 전달받은 authentication 과 usernamePasswordAutheticaionToken이 일치하는걸 확인할수 있고 여기서 이제 검증을 시도하게되는데 검증을 하기위해 전에 만들었던 클래스를 사용하여 검증하게 된다. 확인해보면 정상적으로 accountContext를 얻어왔고 안에는 Account객체가 있는걸 확인할수 있다. 여기 에는 user에 해당하는 정보가 담겨 있다.
현재는 일치하기 때문에 예외를 발생하지 않고 UsernamePasswrodAuthenticationToken 으로 넘어간다 이후에는 TOKEN 을 생성하고 Account 객체와 , 권한정보 를 저장해서 새로운 인증객체를 만들어서 Provider를 호출한 즉 이클래스를 호출한 AuthenticationManager에게 전달한다. 자세하게 말하면 AuthenticationManager를 구현한 ProviderManager 에게 전달한다.
과정을 살펴 보면 result라는 개체가 현재 널이 아닌걸 확인이 되고 인증이 된 이후에 추가적인 작업을 하는 과정이다. 이후에 SecurityContextHolder에 저장한다.
'SpringSecurity' 카테고리의 다른 글
SpringSecurity(로그아웃 및 인증에 따른 화면 보안처리) (0) | 2020.11.25 |
---|---|
SpringSecurity( 커스텀 로그인 페이지 생성하기) (0) | 2020.11.25 |
SpringSecurity(Form 인증구현) (0) | 2020.11.20 |
SpringSecurity(사용자 DB등록 및 PasswrodEncoder) (0) | 2020.11.15 |
SpringSecurity 프로젝트 구성 (0) | 2020.11.13 |