java, spring

[Spring] 스프링 시큐리티 간단한 로그인과 로그아웃 처리

isaac.kim 2021. 9. 25. 00:50
728x90
반응형

[Spring] 스프링 시큐리티 간단한 로그인과 로그아웃 처리

 

이전 글

2021.09.24 - [Spring] - [Spring] Spring Web Security

2021.09.24 - [Spring] - [Spring] Spring Web Security의 설정


접근 제한 설정

security-context.xml에 접근 제한을 설정합니다.

특정한 URI에 접근할 때 인터셉터를 이용해서 접근을 제한하는 설정은 <security:intercept-url>을 이용합니다. <security:intercept-url>은 pattern이라는 속성과 access라는 속성을 지정해야만 합니다. pattern 속성은 말 그대로 URI의 패턴을 의미하고, access의 경우는 권한을 체크합니다. 위 '/sample/member'라는 URI는 'ROLE_MEMBER'라는 권한이 있는 사용자만이 접근할 수 있습니다.

 

access의 속성값으로 사용되는 문자열은 1) 표현식과 2) 권한명을 의미하는 문자열을 이용할 수 있습니다. <security:http>는 기본 설정이 표현식을 이용하는 것입니다.

 

만일 단순한 문자열만을 이용하고 싶은 경우에는 use-expressions="false"를 지정합니다.

 

표현식을 사용하지 않는 경우(권장되지 않음)

 

security 설정을 변경하고 WAS를 실행한 후 '/sample/member'를 접근해 보면 '/sample/all'과는 달리 '/sample/member'는 로그인 페이지로 강제로 이동하는 것을 볼 수 있습니다.

/sample/member 호출 시 강제로 로그인 페이지로 이동

신기한 점은 '/login' 에 해당하는 컨트롤러나 웹페이지를 제작한 적이 없다는 사실입니다. 스프링 시큐리티가 기본으로 제공하는 페이지인데, 현실적으로 별도의 로그인 페이지를 제작해야만 하므로 테스트하는 과정에서만 사용할 만합니다.


단순 로그인 처리

※ 스프링 시큐리티에서 주의해야 할 단어

- 일반 시스템에서 userid는 스프링 시큐리티에서는 username에 해당합니다. 일반적으로 사용자의 이름을 username이라고 처리하는 것과 혼동하면 안 됩니다.

- 스프링 시큐리티에서 User는 인증 정보와 권한을 가진 객체이므로 일반적인 경우에 사용하는 사용자 정보와는 다른 의미입니다. 이를 구분하기 위해 시스템상의 회원 정보는 MemberVO라는 클래스를 이용합니다.

 

단순 로그인 처리 확인을 위해 메모리상에 문자열을 지정하고 이를 기준으로 동작하도록 설정해 봅니다.

 

인증과 권한에 대한 실제 처리는 UserDetailsService라는 것을 이용하는데, XML에서는 다음과 같이 지정할 수 있습니다.

 

security-context.xml

추가된 설정의 핵심은 'member'라는 계정 정보를 가진 사용자가 로그인을 할 수 있도록 하는 것입니다.

 

스프링 시큐리티 5버전부터 반드시 PasswordEncoder라는 존재를 이용하도록 변경되었습니다. 스프링 시큐리티 4버전까지는 PasswordEncoder의 지정이 없어도 동작했지만, 5버전부터는 PasswordEncoder의 지정이 반드시 필요합니다.

만일 패스워드 인코딩 처리없이 사용하고 싶다면 패스워드 앞에 '{noop}' 문자열을 추가합니다.

다시 WAS를 실행해서 '/sample/member'에 접근하고 'member/member'로 로그인하면 '/sample/member' 페이지를 볼 수 있습니다.


로그아웃 확인

개발자 도구 > Application > Cookies 항목에 JSESSIONID(Tomcat에서 발행하는 쿠키 이름) 와 같이 세션을 유지하는데 사용되는 세션 쿠키의 존재를 확인할 수 있습니다.

 

로그아웃은 JSESSIONID 쿠키를 강제로 삭제해서 처리합니다.

웹 화면을 이용하는 로그아웃은 추후 처리하도록 합니다.


여러 권한을 가지는 사용자 설정

사용자에게 'ROLE_ADMIN'이라는 권한과 'ROLE_MEMBER'라는 2개의 권한을 지정합니다.

Admin 계정을 가진 사용자는 'ROLE_MEMBER, ROLE_ADMIN' 이라는 2개의 권한을 갖도록 설정했고, Admin 계정을 가진 사용자는 '/sample/member'와 '/sample/admin' 모두에 접근할 수 있습니다.


접근 제한 메시지의 처리

권한이 없는 사용자가 로그인 했을 때 다음과 같은 페이지가 나타납니다.

스프링 시큐리티에서는 접근 제한에 대해 AccessDeniedHandler를 직접 구현하거나 특정한 URI를 지정할 수 있습니다.

 

security-context.xml

<security:access-denied-handler>는 org.springframework.security.web.access.AccessDeniedHandler 인터페이스의 구현체를 지정하거나 error-page를 지정할 수 있습니다. 위 경우 '/accessError'라는 URI로 접근 제한 시 보이는 화면을 처리합니다.

 

com.project.controller.CommonController 클래스를 생성해서 '/accessError'를 처리하도록 지정합니다.

accessError.jsp 페이지 생성 및 작성

접근 제한 페이지가 나오도록 admin페이지를 member로 로그인합니다. JSP에선 HttpServletRequest 안에 'SPRING_SECURITY_403_EXCEPTION'이라는 이름으로 AccessDeniedException 객체가 전달됩니다.


AccessDeniedHandler 인터페이스를 구현하는 경우

<security:access-denied-handler error-page="/accessError" /> 와 같이 error-page만을 제공하는 경우 위에서 본 바와 같이 URI 자체의 변화는 없습니다. 위 그림에서도 URI 자체는 '/sample/admin'으로 되어 있고, 화면의 내용은 '/accessError'에 해당하는 URI의 결과입니다.

 

접근 제한이 된 경우에 다양한 처리를 할 경우라면 직접 AccessDeniedHandler 인터페이스를 구현하는 편이 좋습니다.

 

com.project.security 패키지를 생성하고 CustomAccessDeniedHandler 클래스를 추가합니다.

CustomAccessDeniedHandler 클래스는 AccessDeniedHandler 인터페이스를 직접 구현합니다. 인터페이스의 메서드는 handle( ) 뿐이기 때문이고 HttpServletRequest, HttpServletResponse를 파라미터로 사용하기 때문에 직접적으로 서블릿 API를 이용하는 처리가 가능합니다.

 

위 코드는 접근 제한에 걸리는 경우 리다이렉트 하는 방식으로 동작하도록 지정되었습니다. security-context.xml에서 error-page 속성 대신에 CustomAccessDeniedHandler를 빈으로 등록해서 사용합니다.

 

security-context.xml

<security:access-denied-handler>는 error-page 속성과 ref 속성 둘 중 하나만 사용합니다.

 

접근 제한 페이지가 나타나도록 시도합니다. => /accessError 로 리다이렉트되는 것을 확인할 수 있습니다.


코드로 배우는 스프링 웹 프로젝트 책을 참고하여 작성했습니다.

728x90
반응형