• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    해결됨

AjaxLoginAuthenticationEntryPoint 관련 질문입니다.

24.02.11 20:42 작성 24.02.14 00:00 수정 조회수 135

0

안녕하세요 강의 잘 듣고 있습니다!!

저는 [스프링 부트 v3.1.3 , 스프링 시큐리티 6.2 버전]으로 강의를 듣고 구현해보고 있습니다!

AjaxLoginAuthenticationEntryPoint(), ajaxAccessDeniedHandler()에서 계속 401 에러 [로그인이 안되어 있음]가 발생하여 해결 방안을 찾지 못하고 질문 올립니다.

테스트 사진에서 admin() 버튼을 눌렀을 때, manager 권한으로 provider에서 잘 실행이 된 후, 곧이어 "/api/message.do" get 방식으로 호출한 상태를 나타냅니다. (결과 : 401 에러, 예측 값 : message ok가 되야함)

 

세션 쿠키도 잘 생성이 되고 있지만, 다시 /api/message.do으로 보낼때, AnonymousAuthenticationToken으로 넘어가고 있습니다... 어디선가 초기화가 되는 것일까요...?

 

@Bean
    public SecurityFilterChain allfilterChain2(HttpSecurity http) throws Exception { 
		
    	http.csrf(csrf ->csrf.disable())
    	.securityMatcher("/api/**")
        .authorizeHttpRequests(request -> request
        	    .dispatcherTypeMatchers(DispatcherType.FORWARD).permitAll() // 맨 처음
				.requestMatchers(new AntPathRequestMatcher("/api/login")).permitAll() //여기 경로만 탈때 ajaxSecuriyConfig가 작동을 하게 되는 것이다.
				.requestMatchers(new AntPathRequestMatcher("/api/messages.do")).hasRole("MANAGER")
                .anyRequest().authenticated()	// 어떠한 요청이라도 인증필요
        )
        .exceptionHandling(handling ->handling
        		.accessDeniedHandler(ajaxAccessDeniedHandler())
        		.authenticationEntryPoint(new AjaxLoginAuthenticationEntryPoint())
        )
        .addFilterBefore(ajaxLoginProcessingFilter(authenticationManager(http)), UsernamePasswordAuthenticationFilter.class);
        ;
        
      return http.build();
    }

 

function getMessege() {
	  $.ajax({
		 url: '/api/messages.do',
		 type: 'get',
		 dataType: 'json',
		 contentType: "application/json",
		 data: {},
		 success: function(res){
         // ajax 통신 성공시 호출
			 console.log(res);
		 },
		 error: function(xhr, status, error) {
        // 요청이 실패했을 때 실행될 콜백 함수
        console.log('Error:', xhr.responseText);
    }
	  });
  }

 

 

function admin() {
	  $.ajax({
		 url: '/api/login',
		 type: 'post',
		 dataType: 'json',
		 contentType: "application/json",
		 data: JSON.stringify({
			 user_name : "manager",
  			 password : "1234rf"
		 }),
		 success: function(res){
         // ajax 통신 성공시 호출
			 console.log(res);
			 getMessege();
		 },
		 error: function(xhr, status, error) {
            console.error('Error:', xhr.responseText);
        }
	  });
  }

 

401에러.png

답변 2

·

답변을 작성해보세요.

0

이 부분은 저도 테스트를 해 봐야 정확한 원인을 알 것 같습니다.

소스 공유 부탁드립니다.

다만 최신 버전으로 인한 문제일 경우 정확한 답변들 드릴 수 없음을 양해 바랍니다.

김상욱님의 프로필

김상욱

질문자

2024.02.19

안녕하세요 제가 export 하여 프로젝트를 말아 드리고자 하는데 어떻게 보내드리면 될까요...?? ㅠㅠ

혹시 깃헙으로는 공유가 안될까요?

안되신다면 onjsdnjs@gmail.com 으로 보내 주시면 됩니다

김상욱님의 프로필

김상욱

질문자

2024.02.21

선생님 메일 보내드렸습니다!!

검토 부탁드리겠습니다 ㅠㅠ

0

인프런 AI 인턴님의 프로필

인프런 AI 인턴

2024.02.13

안녕하세요, 인프런 AI 인턴입니다.
김상욱님의 질문 잘 보았습니다.

우선 아래의 점들을 확인하시는 것이 좋겠습니다.

  1. Spring Security의 SecurityFilterChain에 정의된 url 패턴과 실제 요청 url이 일치하는지 확인하여야 합니다. “/api/messages.do”에 접근할 때 ‘MANAGER’ 역할을 가진 사용자만 접근이 가능하도록 되어 있습니다. 로그인 후 해당 역할을 가진 인증 토큰이 세션이나 SecurityContext에 정상적으로 저장되고 있는지 확인해야 합니다.

  2. Ajax 요청에 대하여 서버가 인증 상태를 유지하는지 확인할 필요가 있습니다. 예를 들어서, 세션 방식을 사용한다면 로그인 이후 생성된 세션이 Ajax 호출에도 올바르게 포함되어 전송되는지 체크해야 합니다. 세션이 아닌 토큰 기반 인증을 사용한다면, 인증 토큰이 요청 헤더에 올바르게 포함되는지 확인해보세요.

  3. 만약 인증 상태를 유지하는 데 문제가 없다면, Spring Security 설정에서 예외를 처리하는 방식이 올바른지 확인해 보세요. 인증되지 않은 사용자에 대한 요청이 AjaxLoginAuthenticationEntryPoint로 적절히 넘어가서 처리되는지 로그를 통해서 확인이 필요할 수 있습니다.

  4. 사용자가 ‘MANAGER’ 역할을 가지고 있는지 확인해볼 필요도 있습니다. 자바 코드에서 사용자 권한을 부여하는 부분을 확인해 보셔서, ‘MANAGER’ 역할이 제대로 부여되었는지 체크해보세요.

  5. 브라우저의 개발자 도구를 통해 로그인 요청과 메시지 요청의 헤더를 확인해보세요. 특히 인증 관련 헤더가 정상적으로 설정되어 있는지 확인이 필요합니다.

위의 사항들을 확인하시고도 문제가 해결되지 않는다면, 인증 실패에 대한 로그나 에러 메시지를 좀 더 자세히 살펴보시는 것도 한 방법입니다.

부디 문제가 원활히 해결되기를 바랍니다.

김상욱님의 프로필

김상욱

질문자

2024.02.14

image

ajax success handler 이후, 필터 체인 프록시에서 SecurityContextHolderFilter에 clearContext()를 찍고 인증이 초기화가 되는 것을 확인하였습니다! 왜 그런 것일까요??!

김상욱님의 프로필

김상욱

질문자

2024.02.16

image오늘도 해결 되지는 않았지만,,, 이 필터들을 자세히 보고 디버깅을 찍어보았습니다.

formLogin 방식에서는 권한이 유지가 되고 있어서 AjaxLogin 방식과 비교를 해보았습니다.

Form 방식의 로직에서는 [4]LoginFilter > 인증로직 Provider.class > 성공 > successHandler.class > [1]Disable..Filter > [12]까지 권한이 유지되었음.

Ajax 방식의 로직에서는 [4]LoginFilter > 인증로직 Provider.class > 성공 > successHandler.class > [1]Disable..Filter에서부터 유지가 되지 않았음.

 

따져보니 response.setStatus(HttpServletResponse.SC_OK); 후 writeValue()를 하였지만, response가 초기화가 되어진 상황인 것 같습니다!

 

이 경우 어느 쪽을 살펴 봐야 할 지 조언을 부탁드리겠습니다.

김상욱님의 프로필

김상욱

질문자

2024.02.16

마지막 Ajax successHandle에서 request를 확인해 보았을때, formLogin에서의

{SPRING_SECURITY_CONTEXT=SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=admin, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[ROLE_ADMIN]], Credentials=[PROTECTED], Authenticated=true, Details=FormWebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=9379D800AC35AD3756A9A45E7169D0C2], Granted Authorities=[ROLE_ADMIN]]]}

이렇게 과거 session이 저장되어 있었습니다. Ajax Login 방식에서는 어디를 고쳐야 할까요...??