본문 바로가기
Spring

[Spring] Spring Security 접근제한 페이지 커스텀

by jane.dev 2021. 11. 3.
반응형

특정 url에 대한 접근 제한을 설정하고

<security:http>
    <!-- 인터셉터를 이용해 특정 URI에 접근을 제한 -->
    <security:intercept-url pattern="/all" access="permitAll"/>
    <security:intercept-url pattern="/member" access="hasRole('ROLE_MEMBER')"/>
    <security:intercept-url pattern="/admin" access="hasRole('ROLE_ADMIN')"/>
</security:http>

'ROLE_MEMBER'의 권한만 부여된 사용자와 같이 권한 미충족 사용자가 'ROLE_ADMIN'의 권한이 필요한 페이지로 접속하게 되면

 

위와 같이 접근제한 페이지가 나타나면서 403 에러(접근 거부, Access Denied) 발생

톰캣에서 기본으로 제공하는 해당 페이지를 커스텀해서 화면 처리

 

security-context.xml

<security:http auto-config="true" use-expressions="true">
    <!-- 스프링 시큐리티에서 제공하는 기본 에러 페이지 처리  -->
    <security:access-denied-handler error-page="/accessError"/>
</security:http>

'/accessError'라는 주소로 접속하면 에러페이지로 이동할 수 있도록 작성

 

CommonController.java

@Controller
public class CommonController {
	// 접근 제한
	@GetMapping("/accessError")
	// Authentication: 어떠한 접근권한인지 
	public void accessDenied(Authentication auth, Model model) {
		log.info("접근 거부: " + auth);
		model.addAttribute("errorMessage", "요청하신 페이지에 접근권한이 없습니다.");
	}

'/accessError'로 접속하는 요청에 대한 처리

 

accessError.jsp

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!-- spring security 관련 태그 라이브러리 -->
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="sec" %>
<body>
	<h1>접근에 실패했습니다.</h1>
	<!-- jsp에서 HttpServlet Request안에 PRING_SECURITY_403_EXCEPTION 이라는 이름으로
         AccessDeniedException 객체가 전달됨-->
	<h2><c:out value="${SPRING_SECURITY_403_EXCEPTION.getMessage() }"/></h2>
	<h2><c:out value="${errorMessage }"/></h2>
</body>

 

 

커스텀을 위해 수정

CustomAccessDeniedHandler.java

AccessDeniedHandler 인터페이스를 구현

// 로그인 및 권한을 사용자가 커스터마이징할 수 있도록 스프링 시큐리티 내부에 미리 구현되어있는 일종의 템플릿
@Log4j
public class CustomAccessDeniedHandler implements AccessDeniedHandler{
	@Override
	public void handle(HttpServletRequest request, HttpServletResponse response,
	  AccessDeniedException accessDeniedException) throws IOException, ServletException {
		log.error("커스텀된 접근 거부 핸들러 실행");
		log.error("/accessError 페이지로 redirect");
		// 로그인이 실패할 경우 해당 페이지로 리다이렉트
		response.sendRedirect("/accessError");
	}
}

 

security-context.xml

<!-- 커스텀된 AccessDeniedHandler를 사용할 수 있도록 빈 저장 -->
<bean id="customAccessDenied" class="org.ict.security.CustomAccessDeniedHandler"/>

<security:http auto-config="true" use-expressions="true">
    <!-- default 설정 대신 커스텀핸들러를 사용할 수 있도록 수정
    <security:access-denied-handler error-page="/accessError"/>  -->
    <security:access-denied-handler ref="customAccessDenied"/>
</security:http>

 

accessError.jsp

<body>
	<div>
		<i class="fas fa-exclamation-triangle"></i>
		<h1><c:out value="${errorMessage }"/></h1>
		<p>연결하려는 페이지에 접근권한이 없어 접근이 거부되었습니다.</p>
		<p>서비스 이용에 불편을 드려 죄송합니다.</p>
	</div>
	<div>
		<a href="#"><button>이전페이지</button></a>
		<a href="#"><button>홈으로</button></a>
	</div>
</body>