일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- 메소드
- STOMP
- 자료구조
- 자동화워크플로우
- 스프링시큐리티
- 테스트케이스
- 프로토콜역할
- 티스토리챌린지
- 프로세스와스레드의차이
- 한화시스템부트캠프
- jwt토큰
- XSS
- kafka배포
- 헥사고날아키텍처
- 캐시의 작동 원리
- 하이브리드접근법
- JPA
- 부트캠프
- 자바
- springboot
- 오블완
- QA
- N+1문제
- Kafka
- selenium
- Java
- n8n
- 오버로딩
- nplus1
- 엘라스틱서치
- Today
- Total
아쿠의 개발 일지
한화 시스템 부트 캠프 10주차 회고 본문
여러분들은 로그인을 직접 구현 해 보셨습니까.
지금까지는 CRUD에 매진 했다면 10주 차는 로그인! 로그인! 로그인! 에 매진했다.
지금까지 기본적인 CRUD를 구현하는 것에 대해 연습했다면 이제는 로그인 구현을 해서 저번에 배운 개념,,,이었던
토큰을 직접 받아왔고. 그 토큰을 통해 서비스 인증과 권한을 부여을 해서
게시글 작성 또는 로그인을 하게 해 주는,,,!! 네! 그렇습니다!!
망할(로그인) 시작 해 보겠습니다 🧡💛
시작 하기 전 교육장에서 나눠준 " 스프링 부트 핵심 가이드 " 책을 참고하면서 작성 했습니다.
어차피 이거로 공부 했거든요... 정말 친절한 설명이 적혀있습니다. 하지만 우리 강사님이 더 친절함.
개발을 하다 보면 인증과 인가 등의 보안 기능을 추가해야 할 때가 있다.
스프링에 보안을 적용할 때 사용하는 <스프링 시큐리티>에 대해서 공부했다.
지금까지는 화면이 없는 무상태 REST 애플리케이션이었기 때문에 로그인을 통한 일반적인 인증과 인가 방식이 아닌 매 요청마다 토큰 값을 활용하는 보안 기법에 대해서! 적어보겠다.
위 그림의 필터체인은 서블릿 컨테이너에서 관리하는 ApplicationFilterChain을 의미한다.
클라이언트에서 애플리케이션으로 요청을 보내면 서블릿 컨테이너는 URL을 확인해서 필터와 서블릿을 매핑한다.
스프링 시큐리티는 사용하고자 하는 필터체인을 서블릿 컨테이너의 필터 사이에서 동작시키기 위해 .DelegatingFilterProxy를 사용한다.
보안 필터체인은 WebSecurityConfigurerAdapter 클래스를 상속받아 설정할 수 있다. 앞에서 이야기한 것 처럼 필터체인 프록시는 여러 보안 필터체인을 가질 수 있는데 여러 보안 필터체인을 만들기 위해서는 WebSecurityConfigurerAdpter 클래스를 상속받는 클래스 여러개를 생성하면 된다. 상속받은 클래스에서 @Order 어노테이션을 지정해 순서를 정의하는 것이 중요하다.
별도의 설정이 없다면 스프링 시큐리티에서는 다음 그림과 같이 SecurityFilterChain에서 사용하는 필터 중 UsernamePasswordAuthenticationFilter를 통해 인증을 처리한다 (진짜 길다...😂)
위 그림의 인증 수행 과정을 설명 해 드리겠습니다.
1. 클라이언트로부터 요청을 받으면 서블릿 필터에서 SecurityFilterChain으로 작업이 위임되고 그 중 AuthenticationFilter에서 인증을 처리한다.
2. AuthenticationFilter는 요청 객체에서 username과 password를 추출해서 토큰을 생성한다.
3. 그러고 나서 AuthenticationManager에게 토큰을 전달한다.
4. ProviderManager는 인증을 위해 AuthenticationProvider로 토큰을 전달한다.
5. AuthenticationProvider는 토큰의 정보를 UserDetailsService에 전달한다.
6. UserDetailsService는 전달받은 정보를 통해 데이터베이스에서 일치하는 사용자를 찾아 UserDetails 객체를 생성한다.
7. 생성된 UserDetails 객체는 AuthenticationProvider로 전달되며, 해당 Provider에서 인증을 수행하고 성공하게 되면 ProviderManager로 권한을 받은 토큰을 전달한다.
8. ProviderManager는 검증된 토큰을 AuthenticationFilter로 전달한다.
9. AuthenticationFilter는 검증된 토큰을 SecurityContext에 저장한다.
이런 내용이다. 그림을 보면 이해가 잘 안 가긴 해도 정말 직접 해 보는 게 중요한 것 같다.
public class LoginFilter extends UsernamePasswordAuthenticationFilter {
private final JwtUtil jwtUtil;
private final AuthenticationManager authenticationManager;
public LoginFilter(JwtUtil jwtUtil, AuthenticationManager authenticationManager) {
this.jwtUtil = jwtUtil;
this.authenticationManager = authenticationManager;
}
public LoginFilter(AuthenticationManager authenticationManager, JwtUtil jwtUtil, AuthenticationManager authenticationManager1) {
super(authenticationManager);
this.jwtUtil = jwtUtil;
this.authenticationManager = authenticationManager1;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
PostLoginReq dto;
try {
ObjectMapper objectMapper = new ObjectMapper();
ServletInputStream inputStream = request.getInputStream();
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
dto = objectMapper.readValue(messageBody, PostLoginReq.class);
} catch (IOException e) {
throw new RuntimeException(e);
}
String username = dto.getEmail();
String password = dto.getPassword();
// 그림에서 2번
UsernamePasswordAuthenticationToken authToken =
new UsernamePasswordAuthenticationToken(username, password, null);
// 그림에서 3번
return authenticationManager.authenticate(authToken);
}
// 그림에서 10번
@Override
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
CustomUserDetails user = (CustomUserDetails)authResult.getPrincipal();
Collection<? extends GrantedAuthority> authorities = authResult.getAuthorities();
GrantedAuthority auth = authorities.iterator().next();
String role = auth.getAuthority();
String username = user.getUsername();
Long idx = user.getMember().getIdx();
String token = jwtUtil.createToken(idx, username, role);
response.addHeader("Authorization", "Bearer " + token);
PrintWriter out = response.getWriter();
out.println("{\"isSuccess\": true, \"accessToken\": \""+token+"\"}");
}
}
내용이 길기에 import와 package는 지웠다.
이는 LoginFilter를 구현한 것이고, 주석으로 달아두긴 했지만 그림에서 2번과 3번 10번이 해당되어 있다.
username과 password를 추출해서 만든 토큰을 담아 2번으로 전달하는 것이고,
이제 이 토큰을 AuthenticationManager로 보내는 것이다.
다음 사진으로는 직접 공부한 내용을 올릴 것인데 정말 상세하게 다 적었다. 필요하신 분이 계시면 공부하셔요...
사진을 보면 아시겠지만 한번 더 설명을 드리자면
처음 loginfilter에는
1번 . /attemptAuthentication
2번 . /successfulAuthentication
이렇게 메소드가 나뉘어져 있다. 처음 실행 할 때는 1번을 실행하고, DB에 전달하고 다시 되돌아가서 2번을 수행하는 것이다. 물론 로그인이 성공 했다면 말이다. 화살표를 보면 DB에 갔다가 customUserDetails 객체를 반환하고 이 객체를 확인해서 보내주는 것이다. 반복되게 인증을 수행한다고 생각하면 좋다.
이렇게 로그인 구현에 대해서 알아보았다. 카카오 로그인, 구글 로그인 같은 소셜 로그인은 지금보다 더 복잡하고 추가해야 할 것이 많은데, 이는 다시 공부 해 보고 오도록 하겠다.!
그냥 잘 만들어진 거 써라
Keep
끝까지 파고 들라고 하기.
처음에는 강사님께 질문하는 것이 어려웠는데, 요즘은 정말 안 되면 스스로 간다.
혼자 잡고 있으면서 시간을 버리는 것 보다 빠르게 해결하고 복습하고 나아가는 것이 중요함을 로그인하면서 느꼈다.
요즘 아침 일찍 와서 강의실 쓰레기도 줍는다,,, 내 자리 청소 하는 습관 좀,,, 응 그러자
TMI 강사님이 제빙기를 구매하셨다. 우리 강의실 사람들이 얼음을 꽤나 많이,,, 사먹더라.
그래서 내돈내산 제빙기를 선사해주셨다. 나는 아침에 조금 빨리 와서 물도 채워놓고,,, 관리도 나름 하려고 노력한다.
다들 몰랐죠? ㅠ
Problem
당을 끊자.
통근하면서 강의 좀 들어라. 오늘 그래도 예외처리에 대해서 들으면서 왔다.
Try
혼자 구현 좀 해봐라. 코테 문제 좀 풀어봐라. 초반에는 그래도 스프링만큼 빡세지 않았기에 여유가 있었던 거 같은데 지금은 여유는,,, 없는 거 같고 다음 주에 있을 토이 프로젝트가 걱정이다. 3일만에 구현을 다 하라니. 이게 뭔? ㅠㅠ 😂😂

얘처럼 감정적으로 살지 맙시다. 이번 주도 힘내요 다들!
'ETC > 한화시스템' 카테고리의 다른 글
한화 시스템 부트 캠프 12주차 회고 (10) | 2024.07.22 |
---|---|
한화 시스템 부트 캠프 11주차 회고 (10) | 2024.07.14 |
한화 시스템 부트 캠프 6월 회고 (2) | 2024.07.09 |
한화 시스템 부트 캠프 9주차 회고 (4) | 2024.07.09 |
한화 시스템 부트 캠프 8주차 회고 (38) | 2024.06.22 |