안녕하세요. 강의 잘 보고,듣고, 익히고 있습니다! customAuthenticationFilter관련 부분보다가 궁금증이 생겨서 질문 남깁니다. authenticationManager, authenticationProvider 로직을 SecuriyConfig의 필터가 아닌 일반 서비스 로직 내부에서도 똑같이 커스텀해서 사용이 가능한가요? (Contoller에서 dto로 받아서 서비스에서 id/pw 검증 후 이후 과정을 처리하는 그런 흐름이 가능한건지 궁금합니다) jwt 관련 로그인을 구현하려고 하는데, 전체적인 구조는 SpringSecurity의 맥락을 그대로 가져가고 싶은..생각입니다.
HttpSecurity에서 가져오는 AuthenticationManagerBuilder와 주입받는 AuthenticationManagerBuilder가 사로 다르지만 타입이 같아 메서드는 똑같을텐데 managerBuilder.authenticationProvider(new DaoAuthenticationProvider()); builder.authenticationProvider(new DaoAuthenticationProvider()); 후자일경우 수업 내용처럼 부모 프로파이더에는 DaoAuthenticationProvider() 가 들어가고 providers 에는 커스텀과 익명 프로바이더 2개가 들어가는데요 전자 즉 직접 참조하는 AuthenticationManagerBuilder는 부모 프로바이더는 null 인데 반해 기존 providers 에 생겨서 총 3개가되고있습니다 물론 실제 실행할때에는 똑같은 결과지만 함수authenticationProvider 은 public AuthenticationManagerBuilder authenticationProvider(AuthenticationProvider authenticationProvider) { this.authenticationProviders.add(authenticationProvider); return this; } 인데 왜 각각의 작동이 다른지 궁금합니다
강의 내용 중에 POST 와 같이 데이터를 변경하는 요청의 경우 csrf 토큰을 생성한다는 내용이 있는데 로그인 페이지 요청시 GET 으로 요청하는데 csrf 토큰이 input 태그에 포함되어 있는 걸로 보아 POST 와 같이 데이터틀 변경하는 요청의 경우 csrf 토큰을 생성하는 게 아니라 csrf 토큰을 검증하는 것이고, csrf 토큰은 모든 요청에 대해 반환해준다가 맞을까요? 또 csrf 토큰이 난수를 조합해 계속 변경해서 클라이언트에 반환한다고 들었는데 제가 잘못 본 건지 모르겠지만 토큰을 디코딩할 때 난수를 조합하는 코드를 보면 토큰의 길이로 난수를 만드는 것 같은데, 토큰의 길이로 난수를 만든다고 하면 토큰을 변하게 하지 않는 이상 인코딩된 토큰의 결과가 똑같을 것 같거든요. 그래서 세션당 고유 토큰 값은 똑같다고 한다면 로그인 전에는 클라이언트에 반환하는 토큰이 계속 바뀌고 (=익명 사용자 세션이니) 로그인 이후에는 클라이언트에 반환하는 토큰이 일정한 게 아닐까 하는 물음이 생겼습니다. 어느게 맞는 걸까요 ?
' 각 강의 브랜치 주소는 챕터가 시작하는 화면 하단에 표시되어 있으니 참고하여 주시기 바랍니다. ' 라고 하셨는데, 화면 하단에 어디에 있는지 모르겠습니다. 해당 화면에 대해서 스크롤도 안되고, 메모같은 것도 없어서 현재는 github 를 뒤지면서 보고 있는데, 명확한 가이드를 주실 수 있나요 ? 깃허브에 뒤져가면서 보더라도 숫자-내용 basic-내용 형태의 브랜치들 밖에 없다보니 뭘 봐야할지 헷갈립니다.
실제로 UserDetails를 구현하고 있는 건 "AccountContext" 이지 "AccountDTO"가 아니기 때문에, @AuthenticationPrincipal AccountDto accountDto를 하면 null이 반환될 수 있지 않나요? 그래서 차라리 @AuthenticationPrincipal AccountContext accountContext를 해서 if (accountContext != null) { model.addAttribute("username", accountContext.getUsername()); } else { model.addAttribute("username", "비회원"); } 이렇게 하는게 더욱 올바른 방법이 아닌가요?
선생님 , 안녕하세요. 강의 잘듣고 있습니다! 질문이 있어서 글남기게 됩니다! 이번 강의 9분 50초 정도에 AuthoriationManger 인터페이스는 접근제어자가 public으로 되어있는데, 하위 메서드인 verify는 접근제어자가 default로 되어있습니다! 위의 이유가 궁금합니다. AuthrozationManager 와 같은 패키지내의 클래스에서만 verify 메서드에 접근 가능하도록 제한을 두기 위한 것인지 아니면 다른 이유가 있는지 궁금합니다. 답변 부탁드리겠습니다! 항상 좋은 강의 감사드립니다.
SecurityFilterChain 의 순서를 보면 AnonymousAuthenticationFilter 가 먼저이고 AuthorizationFilter 가 맨 마지막에 실행되는 것을 확인했습니다. Anonymous 강의에서 AnonymousAuthenticaionFilter는 authentication이 null 인 경우 AnonymousAuthenticaionToken을 생성하여 익명 사용자로 처리한고 Authentication이 null이 아닌 경우 doFilter()로 다음필터로 넘어간다고 하셨는데. 오늘 강의를 보니 anonymousAuthenticationFilter 에는 authenticaion 이 있는지 확인을 하지 않고 authorizationFilter 에서 getContext().getAuthentication() 을 통해 유무를 확인후 없다면 다시 AnonymousAuthenticationFilter 를 통해 AnonymousAuthenticationToken을 생성시켜 할당하는 것 처럼 보이는데 맞을까요? 즉 anonymousAuthenticationFilter doFilter() --> AuthorizationFilter getAuthentication() --> anonymousAuthenticationFilter에서 생성
해당 강의를 학습하던 도중 indexController 의 다음 메서드가 어떻게 익명사용자인것을 알아채고 해당 토큰을 남기는 걸까 의문점이 생겨 질문을 남깁니다. @GetMapping("/anonymousContext") public String anonymousContext(@CurrentSecurityContext SecurityContext context) { return context.getAuthentication().getName(); } 해당의문을 해결하기 위해 localhost:8080/anonymousContext 가 호출될 때 서버는 어떤 과정을 거칠까 생각해보고 다음과 같은 결론을 냈습니다. 1. localhost:8080/anonymousContext 가 호출될 때, Authentication 이 null 값인 것을 확인한다 2. AnonymousAuthenticationToken을 생성하여 SecurityContextHolder에 저장한다. 3. Jsession이 없는 것을 확인하고 AnonymousAuthenticationToken이 저장된 SecurityContext를 파라미터로 넘긴다. 4. 해당 포큰이 getName() 값이 출력된다. 이러한 과정을 거칠거라 생각한 이유는 로그인 상태에서 localhost:8080/anonymousContext 를 호출하게 될 때, "user"라는 값이 출력되는 것을 확인했고 두 같은 요청값에 유일한 차이는 쿠키에 Jsession의 유무였기 때문입니다. SecurityContext가 anonymous 를 판단하는 기준이 제가 생각한 것과 같을까요?
강의에서 SecurityBuilder를 통해 생성된 SecurityFilterChain 을 저장한다는 설명과 관련해서 어떤 코드가 실행하는지 분석을 나름 해보았는데요, 맞는지 확인받고 싶습니다. WebSecurityConfiguration 클래스에 springSecurityFilterChain() 메서드에 다음과 같은 코드가 있습니다. for(SecurityFilterChain securityFilterChain : this.securityFilterChains) { this.webSecurity.addSecurityFilterChainBuilder(() -> securityFilterChain); } 해당 코드에서 addSecurityFilterChainBuilder() 메서드는 SecurityBuilder<O extends SecurityFilterChain> securityFilterChainBuilder 를 파라미터로 받고 있는데, 해당 파라미터로 람다식을 이용해서 HttpSecurity에서 생성한 객체를 SecurityBuilder의 build() 메서드를 호출시 리턴할 수 있게 () -> securityFilterChain 했고 해당 람다식이 addSecurityFilterChainBuilder() 메서드로 인해 WebSecurity 필드인 securityFilterChainBuilders 에 저장이 되었습니다. 저장된 람다식은 WebSecurity 에 performBuild() 메서드에 구현되어 있는 for(SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : this.securityFilterChainBuilders) { SecurityFilterChain securityFilterChain = (SecurityFilterChain)securityFilterChainBuilder.build(); 다음과 같은 for 문에서 build() 메서드를 호출하면서 SecurityFilterChain 객체를 불러오게 됩니다. 다음과 같은 과정으로 SecurityBuilder 에 저장하고 꺼낼 수 있다고 이해했는데 맞을까요?
안녕하세요. 좋은 강의 올려주셔서 감사하게 잘 듣고 있습니다. Authencation 클래스에 대해서 배우면서 궁금한 점이 생겼습니다. Authentication 클래시는 인증을 할 때, 그리고 인증 후에 인증에 대한 정보로서 두 상황에서 쓰이는 거 같습니다. 그런데 사실 이 두 상황은 상당히 다른 것 같고, 그다지 동일한 값을 쓰지도 않는 것 같습니다. 예를 들어, getCredentials는 인증 할 때만 쓰이고, isAuthenticated같은 경우는 인증 후에만 쓰일 것 같습니다. 이렇게 다른 상황에 쓰이는데도 Authentication 클래스 하나로 합쳐서 쓰는 이유가 있나요? 둘을 구분해 각각의 클래스로 제공하면 더 깔끔할거 같다는 생각이 들어 질문드려봅니다.