SpringSecurity(LoginForm)인증
로그인 인증에 대하여 한번 알아보자 !
출처: 스프링 시큐리티(인프런)
1.사용자가 인증을 시도하게 되면 UsernamePasswordAuthenticationFilter 요청을 받게 된다.
2.AntPathRequestMatcher(/login)
현재 사용자가 url 요청 정보를 확인하고 로그인으로 요청 정보 url이 로그인으로 시작되는지 확인한다
기본값이 login 이다 실패 하게되면 chain.doFilter 여기로 흘러가게 된다
3.Authentication
(Username + Password)
객체를 만들어서 객체안에 로그인할때 입력한 정보들을 저장해서
실질적으로 인증처리를 맞기는 역활을 한다
인증처리를 하기전에 하는 일을 여기서 한다
4.AuthenticationManager
여기서 인증 처리를 하게 되는데 인증관리자 라고 한다인증객체를 받고 처리를 한다
내부적으로 AuthenticationProvider 클래스 타입의 객체를 가지고 있고 인증처리를
AuthenticationProvider 요놈에게 위임한다 이클래스는 실질적으로 인증 처리를 하는 클래스 이다
실패 또는 성공을 리턴하게 되는데 실패 하게 되면 AuthenticationException 요놈을 호출한다
AuthenticationException 요놈은 다시 필터로 받아서 후속 작업을 하게 된다.
성공하게 되면 Authentication 객체를 만들고 인증에 성공한 결과를 AuthenticationManager요놈에게 다시
리턴한다 성공결과는 유저 객체 또는 권한 정도가 되겠다.
5.Authentication
(User+ Authorities)
요놈은 AuthenticationManager요놈에게 인증받은 전달 받는데
최종적으로 성공한 유저 객체와 권한부여 정보를 담은 객체를 받고
SecurityContext 에 저장한다
SecurityContext 요놈은 인증객체를 저장하는 보관소이다
session에도 저장이 된다.
UsernamePasswordAuthenticationFilter 요놈은 두가지로 나눠서 볼수 있다 인증처리 전과 인증처리 후로 보면된다.
소스코드로 한번 보자!
commend+o로 요놈을 먼저 찾아보자
자 그러면 UsernamePasswordAuthenticationFilter클래스가 보일텐데 일단 접어두고!
부모 클래스 부터 확인을하자! 부모 클래스는 AbstractAuthenticationProcessingFilter 이다
이 필터가 하는 역할이 현재 요청하는 사용자의 정보와 내가 인증한 필터에서 설정한 정보 (login)
현재는 login이 아닌 다른 URL로 요청을 했기 때문에 chan.doFilter를 호출한다
로그인하게 되면!
위에 보이듯이 auth = this.attemptAuthentication(request,response);
요놈이 인증을 시도해서 최종적으로 인증에 성공한 객체들을 리턴 받는다
자 그러면 인증을 시도하는 코드로 한번 가보자!
UsernamePasswordAuthenticationFilter 아까 접어두었던 클래스를 보자
여기서 username 과 userpassword 가 있는데 현재 요청한 사용자의 이름과 패스워드가 맞다면!
인증객체를 만들어준다! 자그러면 위에 설명한
Authentication
(Username + Password)
이름과 비밀번호를 추출해서 여기에 저장하는 단계인거다
저장을 한다음에 AuthenticationManager 에게 인증처리를 맞긴다.(인증객체를 전달)
return this.getAuthenticationManager().authenticate(authRequest)
이제 AuthenticationProvider 에게 위임을 하게된다.
provider클래스로 가보자
여기서 객체를 보관하는거 같다 자세한건 아니다 강의내용코드는
for(AuthenticationProvider provider : get Providers()) //여기서 외부에서 생성된 인증된 객체를 보관한다고 되어 있다
아마도 스프링시큐어리티 API가 조금 바뀐듯하다??..
현재 나의 코드는 이렇다
음.. 어쨋든 while 문을 이용해서 현재 접속시도한 유저의 정보와 보관되어 있는 정보가 일치한지 찾아 준다
최종적으로
result= provider.authenicate(authentication); 찾은값을 result에 대입해주고 위임해준다 물론 객체도 전달해준다
여기서 최종적으로 성공 이나 실패 를 리턴하는데 인증에 성공한 후에는
protected Authentication createSuccessAuthentication(Object principal, Authentication authentication, UserDetails user) { UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(principal, authentication.getCredentials(), this.authoritiesMapper.mapAuthorities(user.getAuthorities())); result.setDetails(authentication.getDetails()); return result; }
인증객체를 다시 생성한다 위에 그림을 보면 인증이 성공하면 다시 인증객체(Authentication)를 만드는 순서를 볼수 있다
인증 객체 안에는 유저의 객체와 그사용자에게 부여된 권한정보가 인증객체에 새로 저장된다.
코드상으로 result가 최종적으로 인증 받은 객체를 받아서 반환한다
다시 자기를 호출한 매니저(AuthenticationManager)에게 인증성공한 객체를 전달한다
매니저(AuthenticationManager)는 반환받은 객체를 자기를 호출한 필터(UsernamePasswordAuthenticationFilter)에게 반환한다
return this.getAuthenticationManager().authenticate(authRequest)
여기서 반환받은 객체를 부모 객체(AbstractAuthenticationProcessingFilter)에게 전달되는데
authResult = this.attemptAuthentication(request,response);
최종으로 받게된다.
최종으로 받은 객체를 SecurityContextHolder로 전달한다.
SecurityContextHolder.getContext().setAuthentication(authResult); // 요놈을 사용해서 전형적으로 인증객체를 참조할수 있다.
어떻게 참조 하냐면!
SecurityContextHolder.getContext().getAuthentication(authResult);
set을 get으로 수정해서 사용할수 있다. 장소와 관계없이 어떠한 위치에서든 인증객체를 사용할수 있다.
이후에!
this.successHandler.onAuthenticationSuccess(request,response,authResult);
요놈이 호출되어 나머지 작업들을 처리 한다.
여기까지가 UsernamePasswordAuthenticationFilter가 사용자에게 요청을 받아서 인증처리 하는 과정이다.
소스코드를 통해서 확인을 해봤지만 여전히 모르겠다.. 강의하시는 선생님 뤼스펙합니다!ㅜ
이번강의를 내가 20분짜리를..1시간 반을 봤다.. 어떻게 받고 어떻게 처리하는지는 알겠지만
메서드 내용은 솔직히 잘모르겠다.. 처음보는 코드 라서 그렇다고 위로하고 있지만.. 마음은 안그렇다..
API메서드를 상세하게 알필요는 없다고 하지만 그래도 개념과 로직은 알아야할거 같아서 이렇게 기록에 남긴다
미안 머리야 주인을 잘못만난거 같애