본문 바로가기

스프링

스프링 시큐리티(spring security) 로그인

반응형

들어가기에 앞서 스프링 시큐리티에는 기본적으로 로그인 페이지를 제공합니다.  하지만 현실적으로 화면 디자인 등의 문제로 사용하기 불편합니다. 때문에 대부분 별도의  URI를 이용해서 다시 제작해서 이를 이용하는 방식으로 이전 글인 접근 제한 페이지와 유사하게 직접 URI를 지정할 수 있습니다.

security-context.xml의 일부

	<security:http>
		<security:intercept-url pattern="/sample/all" access="permitAll"/>
        
    ...생략
		
		<!--  <security:form-login/> -->
        
		<security:form-login login-page="/customLogin"/>
        
	</security:http>

login-page 속성의 URI는 반드시 GET 방식으로 접근하는 URI를 지정합니다.

CommonController에 '/customLogin'에 해당하는 메서드를 추가합니다.

CommonController의 일부

		@GetMapping("/customLogin")
		public void loginInput(String error, String logout, Model model) {
			log.info("error : " + error);
			log.info("logout : " + logout);
			
			if(error != null) {
				model.addAttribute("error","로그인 실패 아이디비밀번호를 확인하세요");
			}
			
			if(logout != null) {
				model.addAttribute("logout","로그아웃");
			}
		}

GET 방식으로 접근하고, 에러메시지와 로그아웃 메시지를 파라미터로 사용할 수 있습니다.

이제 view폴더에 customLogin.jsp를 추가합니다.

customLogin.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http//
www.w3.org/TR/html4/loose.dtd>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1>Custom Login Page</h1>
	<h2>${error}</h2>
	<h2>${logout}</h2>
	
	<form action="/login" method="post">
		<div>
			<input type="text" name="username" value="admin"/>
		</div>
		<div>
			<input type="password" name="password" value="pw"/>
		</div>
		<div>
			<input type="submit"/>
		</div>
		<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
	</form>
</body>
</html>

이제 브라우저에서 로그인 정보를 삭제한 후 '/sample/admin'과 같이 접근 제한이 필요한 URI에 접근하면 작성된 customLogin.jsp 페이지의 내용을 볼 수 있습니다. 실제로 로그인 처리 작업은 '/login'을 통해서 이루어지는데 반드시 POST 방식으로 데이터를 전송해야만 합니다.

만일 사용자가 패스워드 등을 잘못 입력하는 경우에는 다시 로그인 페이지로 이동하게 됩니다.

로그인 성공과 AuthenticationSuccessHandler

로그인을 처리하다 보면 로그인 성공 이후 특정한 동작을 하도록 제어해야 하는 경우가 있습니다. 예를 들어 admin 계정으로 로그인했다면 어떤 경로로 로그인을 하던 무조건 'sample/admin'으로 이동하게 하거나 따로 쿠키를 생성해 처리하고 싶은 경우를 생각할 수 있습니다.

이런 경우 스프링 시큐리티에서 AuthenticationSuccessHandler라는 인터페이스를 구현해 설정할 수 있습니다.

CustomLoginSuccessHandler 클래스를 추가합니다.

CustomLoginSuccessHandler 클래스

package com.security.security;

import java.io.IOException;
...생략

import lombok.extern.log4j.Log4j;

@Log4j
public class CustomLoginSuccessHandler implements AuthenticationSuccessHandler{@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
			Authentication auth) throws IOException, ServletException {
	
		log.warn("Login 성공");
		List<String> roleNames = new ArrayList<>();
		
		auth.getAuthorities().forEach(authority -> {
			roleNames.add(authority.getAuthority());
		});
		
		log.warn("Role Names : " + roleNames);
		
		if(roleNames.contains("ROLE_ADMIN")) {
			response.sendRedirect("/sample/admin");
			return;
		}
		if(roleNames.contains("ROLE_MEMBER")) {
			response.sendRedirect("/sample/member");
			return;
		}
		
		response.sendRedirect("/");
		
	}
	
}

AuthenticationSuccessHandler 객체를 이용해서 사용자가 가진 모든 권한을 문자열로 체크합니다.                          사용자가 'ROLE_ADMIN' 권한을 가졌다면 로그인 후에 바로 '/sample/admin'으로 이동하게 합니다.

그리고 security-context.xml 에 위 클래스를 빈으로 등록하고 로그인 성공 후 처리를 담당하는 핸들러로 지정합니다.

security-context.xml의 일부

    <bean id="customAccessDenied" class="com.security.security.
    CustomAccessDeniedHandler"></bean>
	
	<bean id="customLoginSuccess" class="com.security.security.
    CustomLoginSuccessHandler"></bean>
    
    <security:http>
		<security:intercept-url pattern="/sample/all" access="permitAll"/>
		
		<security:intercept-url pattern="/sample/member"
        access="hasRole('ROLE_MEMBER')" />
		
		<security:intercept-url pattern="/sample/admin" 
        access="hasRole('ROLE_ADMIN')"/>
		
		<security:form-login login-page="/customLogin" 
        authentication-success-handler-ref="customLoginSuccess"/>
        
		<security:access-denied-handler ref="customAccessDenied"/>
		
	</security:http>

 

반응형