xml 설정
<bean id="customLoginSuccess"
class="org.project.security.CustomLoginSuccessHandler"></bean>
<bean id="customLooutSuccess"
class="org.project.security.CustomLogoutSuccessHandler"></bean>
<security:http>
<security:form-login login-page="/customLogin"
authentication-success-handler-ref="customLoginSuccess" />
<security:logout
logout-url="/customlogout"
success-handler-ref="customLooutSuccess"
invalidate-session="true"
delete-cookies="remember-me,JSESSION_ID" />
<security:csrf disabled="false"/>
</security:http>
logout-url : 로그아웃 URL
logout-success-url : 로그아웃 성공시, 이동할 URL. (default: /login?logout)
invalidate-session : 로그아웃 시, session을 무효화할 지 선택. (default: true)
security:csrf disabled="false" (default: true)
delete-cookies : 로그아웃 성공시, 삭제할 쿠키 이름 지정
success-handler-ref : 로그아웃 성공시, logout-success-url 이 아닌 핸들러로 리다이렉트(준비할거: 핸들러/ 빈설정)
CustomLogoutSuccessHandler
public class CustomLogoutSuccessHandler implements LogoutSuccessHandler {
@Override
public void onLogoutSuccess(
HttpServletRequest request,
HttpServletResponse response,
Authentication authentication)
throws IOException, ServletException {
if (authentication != null && authentication.getDetails() != null) {
//로그인된 사용자의 인증 객체가 존재하고, 이 객체에 추가적인 세부 정보(details)가 있는지 확인
try {
//request.getSession().invalidate(); // 세션을 무효화 > xml에 설정
//User user = (User) authentication.getPrincipal();
//String username = user.getUsername();
//log.info("------------User " + username + " has been logged out successfully.");
response.setStatus(HttpServletResponse.SC_OK);
response.sendRedirect("/board/getPostList");
} catch (IOException e) {
log.error("--------------Error handling logout", e);
e.printStackTrace();
}
}
}
}
jsp설정
Spring Security와 같은 보안 프레임워크를 사용하는 경우,
/logout URL로 접근하면 Spring Security가 해당 요청을 인터셉트하여 로그아웃을 처리한다.
JSP 페이지(href="/logout")로 이동하는 것이 아니라, Spring Security가 로그아웃을 처리 -> success-handler-ref
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>
...
<sec:authorize access="isAuthenticated()">
<a href="/logout" document.getElementById('logoutForm').submit();">로그아웃</a>
</sec:authorize>
<form id="logoutForm" action="/logout" method="post">
<input name="${_csrf.parameterName}" type="hidden" value="${_csrf.token}" />
</form>
sec태그를 사용하여 로그인한 사용자에게만 로그아웃 버튼이 보이도록한다.
<a href="#" onclick="document.getElementById('logoutForm').submit();">로그아웃</a>
</sec:authorize>
<form id="logoutForm" action="/customlogout" method="post">
<input name="${_csrf.parameterName}" type="hidden" value="${_csrf.token}" />
</form>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="customAccessDenied"
class="org.project.security.CustomAccessDeniedHandler"></bean>
<bean id="customLoginSuccess"
class="org.project.security.CustomLoginSuccessHandler"></bean>
<bean id="customLooutSuccess"
class="org.project.security.CustomLogoutSuccessHandler"></bean>
<bean id="bcryptPasswordEncoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"></bean>
<bean id="customUserDetailsService"
class="org.project.security.CustomUserDetailsService"></bean>
<security:http>
<!-- **인가별분류페이지 -->
<!-- hasAnyRole = or -->
<!-- 유저 -->
<security:intercept-url pattern="/auth/*"
access="permitAll" />
<!-- 관리자 -->
<security:intercept-url pattern="/auth/admin/*"
access="hasRole('ROLE_ADMIN')" />
<!-- 회원 -->
<security:intercept-url pattern="/auth/member/*"
access="hasAnyRole('ROLE_MEMBER','ROLE_MANAGER','ROLE_ADMIN')" />
<security:intercept-url pattern="/auth/member"
access="hasAnyRole('ROLE_MEMBER','ROLE_MANAGER','ROLE_ADMIN')" />
<security:intercept-url pattern="/auth/manager"
access="hasAnyRole('ROLE_MANAGER','ROLE_ADMIN')" />
<security:intercept-url pattern="/auth/admin"
access="hasRole('ROLE_ADMIN')" />
<!-- **인가에러페이지 -->
<!-- <security:access-denied-handler error-page="/accessError" /> -->
<security:access-denied-handler ref="customAccessDenied" />
<!-- **로그인/로그아웃 -->
<!-- <security:form-login/> --> <!-- 로그인 폼이 자동 생성 -->
<security:form-login login-page="/customLogin"
authentication-success-handler-ref="customLoginSuccess" /> <!-- login-page= "" 로그인 리다이렉트 페이지 설정 -->
<!-- 로그아웃 > invalidate-session="true" 세션 정보를 무효화(default: true)-->
<!-- remember-me: 자동로그인 쿠키,JSESSION_ID: WAS가 발행한 쿠키 -->
<!-- header.jsp에 로그아웃 버튼 > (성공) > 핸들러(customLooutSuccess) > (홈) -->
<security:logout
logout-url="/logout"
success-handler-ref="customLooutSuccess"
invalidate-session="true"
delete-cookies="remember-me,JSESSION_ID" />
<!-- 토큰을 사용하기위함. value="${_csrf.token} 디폴트값이 false -->
<security:csrf disabled="false"/>
<!-- 자동로그인 -->
<security:remember-me
data-source-ref="dataSource"
token-validity-seconds="604800" />
</security:http>
<!-- **인증 정보를 설정 -->
<security:authentication-manager>
<security:authentication-provider user-service-ref="customUserDetailsService">
<security:password-encoder ref="bcryptPasswordEncoder" />
</security:authentication-provider>
</security:authentication-manager>
<!-- <security:authentication-manager>
<security:authentication-provider>
<security:jdbc-user-service
data-source-ref="dataSource" />
<security:password-encoder
ref="bcryptPasswordEncoder" />
</security:authentication-provider>
</security:authentication-manager> -->
<!-- <security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user
name="user1"
authorities="ROLE_MEMBER"
password="$2a$10$01MN51JYRf72s2o4Vuxlo.8k/.tcvEt4QEJebrQo8qneYj5/as/OK" />
<security:user
name="admin1"
authorities="ROLE_MEMBER,ROLE_MANAGER,ROLE_ADMIN"
password="$2a$10$01MN51JYRf72s2o4Vuxlo.8k/.tcvEt4QEJebrQo8qneYj5/as/OK" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager> -->
</beans>
https://docs.spring.io/spring-security/reference/servlet/authentication/logout.html