Spring Security 로그인 처리

책을 보면서 가장 이해하기 힘든 부분이었지만 추후 학습할 때 기초적인 개념을 파악하기 위해 정리한 포스팅입니다.

틀리거나 잘못된 부분을 알려주시면 수정하도록 하겠습니다 :)

1. Spring Security

웹사이트는 사용자들에게 권한을 부여하여 등급에 따른 로그인 처리를 합니다. 추가적으로 쿠키나 세션을 이용하여 로그인유지 등의 기능을 사용하기도 하며 스프링에선 Spring Security를 활용하여 이러한 처리를 할 수 있습니다.

Spring Security 는 쉽게 말해 스프링기반의 애플리케이션의 인증과 권한을 담당하는 프레임워크라 말할 수 있으며 InterceptorFilter기반으로 동작하기 때문에 사용시엔 별도의 컨텍스트를 작성하여 처리해야합니다. (스프링 3버전 이후부턴 자바 @bean 어노테이션 설정이 가능합니다.)


1-1. 인증과 권한

  • 인증 : 유저가 누구인지 증명(확인)하는 것
  • 권한 : 어떤 동작을 수행할 수 있는 조건이 충족하는지 결정하는 것

스크린샷 2019-05-21 오후 6 21 43


위 그림은 Spring security의 개념을 설명하는 사진입니다. 요청이 들어오면 인증할 것을 요구하며 이를 통해 인증이 통과되었을시 접근 권한의 정보를 얻어 권한을 부여하고 그에 따른 DB에 접근하여 정보를 얻어가는 과정입니다.

스프링 시큐리티는 인증을 담당하는 AuthenticationManager(인증매니저)가 존재합니다. 인증매니저는 다양한 방식의 인증을 처리할 수 있으며 ProviderManager에 인증처리는 AuthenticationProvider(인증제공자)에게 위임하여 처리합니다. 인증제공자가 실제 인증처리작업을 진행할 때 권한에 정보도 같이 전달되어지는데 이 권한에 대한 처리는UserDetailsService가 처리하게 됩니다. 이 UserDetailsService는 실제 사용자의 정보 + 권한을 리턴해줍니다. 이후 사용자의 정보를 가져와 요청에 대한 응답처리를 하게 됩니다.

2. 접근제한 설정

URI에 대한 접근 제한을 security-context.xml에 작성하였습니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<?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">

	<security:http>
		<security:intercept-url pattern="/sample/all" access="permitAll"/>
		<security:intercept-url pattern="/sample/member" access="hasRole('ROLE_MEMBER')"/>
		
		<security:form-login/>
		
	</security:http>
	
	<security:authentication-manager>
	
	</security:authentication-manager>

</beans>

<security:intercept-url> 태그를 사용하여 pattern(URI)access(접근권한) 속성을 지정합니다.

pattern="/sample/all" -> permitAll

pattern="/sample/member" - > hasRole(‘ROLE_MEMBER’)

permitAll은 모두 허용을 뜻하며, hasRole은 괄호안에 역할만 접근이 가능하단 뜻을 말합니다.

3. 로그인처리와 로그아웃

3-1. 로그인

Spring Secuirty는 접속 ID를 name으로 처리합니다.

위에 내용을 토대로 기본로그인을 security-context.xml 에 작성할 수 있습니다.

1
2
3
4
5
<security:authentication-provider>
			 <security:user-service>
				<security:user name="사용할 ID" password="사용할 Password" authorities="intercept-url의 access 권한"/>
			</security:user-service>
</security:authentication-provider>


3-2. 로그아웃

브라우저의 개발자 도구 Application 탭을 보면 Cookie항목을 확인할 수 있습니다. 이 부분은 톰캣에서 사용하는 쿠키 이름이며 JSESSIONID라 부릅니다. 이 부분을 X 버튼을 누르면 삭제되는 것을 확인할 수 있습니다.

3-3. 로그인 권한

권한은 크게 사용자 및 관리자로 나눌 수 있고 또는 등급으로도 매겨질 수 있습니다. 이는 security-context.xml 에서 설정을 다음과 같이 지정하여 등록할 수 있습니다.

1
2
<security:intercept-url pattern="/sample/member" access="hasRole('MEMBER')"/>
<security:intercept-url pattern="/sample/admin" access="hasRole('ADMIN')"/>

intercept-urlaccess를 지정 후 security-user도 등록해줍니다.

1
2
3
4
 <security:user-service>
   <security:user name="사용할 멤버 ID" password="멤버 비밀번호" authorities="access와 매칭"/>
   <security:user name="사용할 관리자 ID" password="관리자 비밀번호" authorities="access와 매칭(멤버와 관리자 둘다)"/>
</security:user-service>

관리자는 일반 유저와 접근이 동일하게 유지되어야 하기때문에 관리자 user부분의 authorities속성엔 일반 사용자 access도 같이 선언해줍니다.


3-4. 커스텀 로그인

위와 같이 구현시 Spring Security에서 제공하는 기본 로그인페이지로 작동하는데 실제로 사용할 커스텀 로그인페이지를 작성하여 적용하는 법을 알아보겠습니다. (거의 모든 설정이 Spring Security에서 이뤄집니다.)

1
<security:form-login login-page="/myCustomLogin"/>

맨 위에 처음 작성한 security-context.xmlform-login 태그에 login-page 속성을 추가하여 URL을 선언합니다.

이후 Controller와 JSP를 작성합니다.


SecurityController.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@GetMapping("/myCustomLogin")
	public void memberLogin(String error, String logout, Model model) {
		log.info("error : " + error);
		log.info("logout : " + logout);
		
		if(error != null) {
			model.addAttribute("error","Login Error Check u Account");
		}
		
		if(logout != null) {
			model.addAttribute("logout", "logout~~ !!!!!");
		}
		
	}

myCustomLogin.jsp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<%@ 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>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1>Login Page</h1>
	<h2><c:out value="${error }"/></h2>
	<h2><c:out value="${logout }"/></h2>
	
	<form method="post" action="/login">
		<div>
			<input type="text" name="username" value="admin">
		</div>
		<div>
			<input type="password" name="password" value="admin">
		</div>
		<div>
			<input type="submit">
		</div>
		<input type="hidden" name="${_csrf.parameterName }" value="${_csrf.token }">
	</form>
</body>
</html>

화면 페이지

스크린샷 2019-05-22 오후 2 01 24


Reference