인프런 커뮤니티 질문&답변

이지훈님의 프로필 이미지
이지훈

작성한 질문수

스프링 시큐리티

비밀번호 변경 관련 질문입니다.

해결된 질문

작성

·

654

0

안녕하세요 강사님.
해당 강의를 기반으로 시큐리티를 적용한 개인적인 토이 프로젝트를 진행하고 있습니다.

회원정보를 수정하는 기능을 만들었습니다.

문제점

현재 로그인한 A 사용자의 비밀번호를 변경하면
DB에 비밀번호는 잘 업데이트 됩니다.
그런데 SecurityContext에 있는 A의 인증객체가 없어집니다.
(위처럼 생각한 이유는 회원정보를 수정 후 SecurityContextHolder를 이용하여 A를 가져와보니 null값이 나왔고,
  다른 사용자 B로는 로그인이 되었습니다.)

그래서 다시 A로 로그인하게 되면
A는 한번 인증된 사용자이므로 세션에서  SecurityContext를 꺼내서 인증과정을 거치게되는데
SecurityContext에 A의 인증객체가 없어서 로그인이 실패합니다.
(이전 비밀번호, 변경된 비밀번호 모두 실패합니다.)

해결방법

제가 생각한 이론적인 해결방법은 아래와 같습니다.
1. HttpSercurityContextRepository를 직접 구현하던 초기화하던 해서
     A가 처음 로그인하는 사용자라고 인식?하게 만드는 방법

2. 근본적인 문제점을 해결, 즉 없어진 A 인증객체를 SecurityContext에 넣어주는 방법

그런데 이론적인 생각일뿐 어떻게 해야할지 감이 잡히지 않고
구글링 해봐도 정보를 찾기 힘들어서 질문남깁니다..

요약하면
문제점 : A로 로그인 -> 로그인 성공 -> 비밀번호 변경 -> SecurityContext에 A인증객체 사라짐 -> 로그아웃
                -> A로 로그인 -> 로그인 실패

글로 정리가 잘 안되네요ㅠㅠ
위 문제를 어떻게 해결할 수 있을까요..? 

답변 5

1

정수원님의 프로필 이미지
정수원
지식공유자

네 정확한 원인을 찾아서 다행이네요^^

분석하시는 내용을 보니 스프링 시큐리티의 개념을 상세하게 알아가고 있는 것 같습니다.

남은 강의도 잘 들으셔서 더 많은 개념과 흐름을 이해하시고 실무에 적용해 나가시길 바라겠습니다.

1

정수원님의 프로필 이미지
정수원
지식공유자

제가 테스트 한 바로는 위와 같은 현상이 생기지 않습니다.

비밀번호 업데이트 후 SecurityContextHolder.getContext().getAuthentication() 하면 현재 인증된 사용자 정보가 정상적으로 나오고 있습니다.

공유해 주신 소스를 봐도 오류 관련 특이한 점은 발견하지 못했습니다.

비빌번호 업데이트 하는 소스에서 테스트 해 보면

비빌번호 변경 후 정보를 업데이트 하기 전 SecurityContextHolder.getContext().getAuthentication() 의 값이 정상적으로 나오고

정보를 수정한 후 SecurityContextHolder.getContext().getAuthentication() 를 실행해보면 역시 정상적으로 값이 출력되고 있습니다.

그리고 참고로 말씀드리면 인증에 성공한 후 SecurityContext 는 세션에 저장되고 나서 클라이언트로 최종 응답하기 전에  SecurityContext 에 저장한 Authentication 객체의 값은 비워집니다. 즉 SecurityContext.clear() 처리됩니다.

이것은 매 요청마다 이루어집니다.

"A는 한번 인증된 사용자이므로 세션에서  SecurityContext를 꺼내서 인증과정을 거치게되는데

SecurityContext에 A의 인증객체가 없어서 로그인이 실패합니다."

이 의미가 정확하게 어떤 의미인가요?

0

이지훈님의 프로필 이미지
이지훈
질문자

늦은 시간에도 답변 감사합니다.
답변해주신걸 토대로 이것저것 테스트해보고 답변 작성하는 도중에 뭐가 문제인지 깨달았습니다.

애초에 코드에는 문제가 없었습니다...
제가 id,pw를 수정하고
pw는 수정한pw를 입력했는데, id를 수정하기 전 id로 계속 로그인시도를 했습니다ㅠㅠ 

그냥 단순 제 실수였지만 그래도 강사님 덕분에 이것저것 해보면서 문제점을 파악했습니다.
코드도 직접 봐주시고.. 졍말 감사합니다~

---------------------

1.

"A는 한번 인증된 사용자이므로 세션에서  SecurityContext를 꺼내서 인증과정을 거치게되는데

SecurityContext에 A의 인증객체가 없어서 로그인이 실패합니다."

위 의미는
로그인 요청을 했을 때 SecurityContextPersistenceFilter가 요청을 받아서
HttpSecurityContextRepository에게 역할을 위임하는데

HttpSecurityContextRepository가
처음 접근하는 사용자인 경우 새로운 SecurityContext를 생성해서 인증과정을 거치지만
인증된 사용자인 경우 세션에서 SecurityContext를 꺼내서 SecurityContextHoler에 저장 후 다음필터로
넘어간다고 이해했습니다.

그래서 A는 이전에 인증을 했던 사용자이므로 세션에서 SecurityContext를 꺼내서 인증해야하는데
SecurityContext에 A의 인증객체가 없어서 로그인이 실패한다고 생각했었습니다.

그런데 회원 정보를 수정했으니 처음 접근하는 사용자일테고, 그러면 DB에있는 id와 pw를 비교하여 인증시도를하는데
제가 틀린id를 입력했으니.. 당연히 로그인이 안됬던거네요..

2.

제가 null값이 나왔다고 한것은

memberService.updateMember(memberDto); // 회원정보 수정

//회원정보 수정 후
Object principal2 = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
UserDetails userDetails2 = (UserDetails) principal2;
String username2 = userDetails2.getUsername();
Member findMember2 = memberRepository.findByName(username2);
System.out.println(findMember2);

위처럼 코드를 작성했었는데, 회원정보 수정 하면 DB의 값(B)은 업데이트 되겠지만
당연히 인증객체의 값(A)은 변경되지않아 username2 값이 A였고
A로 DB에서 조회하니, DB는 값이 없데이트됬으니 A가 없어서 finMember2가 null값이 나왔었습니다..

그래서 저는 인증객체가 없어졌다고 생각했었네요 ㅠㅠ 
인증객체가 없어졌다면 애초에 첫줄에서 에러가 났었을텐데요.. 

0

이지훈님의 프로필 이미지
이지훈
질문자

여기에는 파일올리는 기능이 없어서
github 링크 남기겠습니다.


https://github.com/znftm97/CRUD

0

정수원님의 프로필 이미지
정수원
지식공유자

가능하시면 소스 공유 부탁드립니다

이지훈님의 프로필 이미지
이지훈

작성한 질문수

질문하기