웹사이트 검색

Spring 4 보안 MVC 로그인 로그아웃 예제


오늘은 스프링 시큐리티 로그인 예제에 대해 알아보겠습니다. 이 게시물을 읽기 전에 "Introduction to Spring 4 Security\에서 이전 게시물을 검토하여 몇 가지 기본 사항을 알아보십시오.

Spring Security 로그인 로그아웃 예제

이번 포스팅에서는 In-Memory 옵션을 이용하여 로그인과 로그아웃 기능을 제공하는 Spring 4 MVC Security Web Application을 개발해 보겠습니다. 이 예제는 Spring Annotations와 함께 Spring Java Config를 사용합니다. 즉, web.xml 및 Spring XML Configuration(Old Style)을 사용하지 않습니다. Spring 3.x Security Module에 익숙하지 않으신 분들은 아래 포스팅을 먼저 보시고 Spring Security Recipe를 맛보시기 바랍니다.

  1. 메모리 내, UserDetailsService 및 JDBC 인증을 사용하는 Spring MVC 보안 예제
  2. DAO, JDBC, In-Memory 인증을 사용하는 서블릿 웹 애플리케이션의 스프링 보안

Spring 4 Security Module은 사용자 자격 증명을 저장하고 관리하기 위해 다음 옵션을 지원합니다.

  1. 메모리 내 저장소
  2. 관계 데이터베이스(RDBMS)
  3. SQL 데이터 저장소 없음
  4. LDAP

이 예제에서는 "In-Memory Store\ 옵션을 사용할 것입니다. 다음 게시물에서 다른 옵션에 대해 논의할 것입니다. Spring 4.0.2.RELEASE, Spring STS 3.7 Suite IDE, Spring TC Server 3.1 with Java 1.8을 사용할 것입니다. 이 예제를 개발하기 위한 Maven 빌드 도구입니다.

스프링 시큐리티 로그인 예제

Spring 4 보안 기능을 사용하여 로그인 및 로그아웃 로직을 개발할 예정입니다. 이 어플리케이션의 주요 목표는 "web.xml\을 사용하지 않고 Spring XML Beans Configuration의 한 줄도 작성하지 않고 어플리케이션을 개발하는 것입니다. 즉, Spring Annotations와 함께 Spring Java Config 기능을 사용할 것입니다. 우리는 이것을 개발할 것입니다. 다음 기능을 갖춘 애플리케이션:

  1. 환영 페이지
  2. 로그인 페이지
  3. 홈 페이지
  4. 로그아웃 기능

이 Spring 4 보안 단순 로그인 예제를 개발하고 탐색하려면 다음 단계를 사용하십시오.

  • 다음 세부 정보를 사용하여 Spring STS Suite에서 "Simple Spring Web Maven\ 프로젝트를 만듭니다.

   Project Name : SpringMVCSecruityMavenApp

  • 다음 콘텐츠로 pom.xml 업데이트

<?xml version="1.0" encoding="UTF-8"?>
<project
   xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 
   https://maven.apache.org/xsd/maven-4.0.0.xsd"
   xmlns="https://maven.apache.org/POM/4.0.0" 
   xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">

	<modelVersion>4.0.0</modelVersion>
	<groupId>com.journaldev</groupId>
	<artifactId>SpringMVCSecruityMavenApp</artifactId>
	<packaging>war</packaging>
	<version>1.0</version>

	<properties>
	    <java.version>1.8</java.version>
	    <spring.version>4.0.2.RELEASE</spring.version>
	    <spring.security.version>4.0.2.RELEASE</spring.security.version>
	    <servlet.api.version>3.1.0</servlet.api.version>
	    <jsp.api.version>2.2</jsp.api.version>
	    <jstl.version>1.2</jstl.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>${spring.security.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
			<version>${spring.security.version}</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>${servlet.api.version}</version>
		</dependency>		
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>jsp-api</artifactId>
			<version>${jsp.api.version}</version>
		</dependency>
		<dependency>
			<groupId>jstl</groupId>
			<artifactId>jstl</artifactId>
			<version>${jstl.version}</version>
		</dependency>
	</dependencies>	

	<build>
	    <finalName>SpringMVCSecruityMavenApp</finalName>
	    <plugins>
		<plugin>
		     <groupId>org.apache.maven.plugins</groupId>
		     <artifactId>maven-compiler-plugin</artifactId>
		     <version>3.1</version>
		     <configuration>
			<source>${java.version}</source>
			<target>${java.version}</target>
		     </configuration>
		</plugin>
		<plugin>
	           <groupId>org.apache.maven.plugins</groupId>
	           <artifactId>maven-war-plugin</artifactId>
	           <configuration>
	              <failOnMissingWebXml>false</failOnMissingWebXml>
	           </configuration>           
        	</plugin>
	    </plugins>
	</build>
</project>

참고:- "\ 플래그를 모르는 경우 이 요소 사용에 대해 잘 이해하기 위해 이 게시물의 끝 부분을 읽으십시오.- 먼저 Spring의 @Controller 주석을 사용하여 로그인 컨트롤러를 개발하십시오.

package com.journaldev.spring.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class LoginController {

	@RequestMapping(value = { "/"}, method = RequestMethod.GET)
	public ModelAndView welcomePage() {
		ModelAndView model = new ModelAndView();
		model.setViewName("welcomePage");
		return model;
	}

	@RequestMapping(value = { "/homePage"}, method = RequestMethod.GET)
	public ModelAndView homePage() {
		ModelAndView model = new ModelAndView();
		model.setViewName("homePage");
		return model;
	}
	
	@RequestMapping(value = "/loginPage", method = RequestMethod.GET)
	public ModelAndView loginPage(@RequestParam(value = "error",required = false) String error,
	@RequestParam(value = "logout",	required = false) String logout) {
		
		ModelAndView model = new ModelAndView();
		if (error != null) {
			model.addObject("error", "Invalid Credentials provided.");
		}

		if (logout != null) {
			model.addObject("message", "Logged out from JournalDEV successfully.");
		}

		model.setViewName("loginPage");
		return model;
	}

}

코드 설명:- 세 가지 다른 종류의 클라이언트 요청을 처리하기 위해 "LoginController”에 세 가지 방법을 정의했습니다.

  1. welcomePage()는 "/\ URI를 사용하는 모든 클라이언트 요청을 처리합니다.
  2. homePage()는 "/homePage” URI를 사용하는 모든 클라이언트 요청을 처리합니다.
  3. loginPage()는 "/loginPage” URI를 사용하는 모든 클라이언트 요청을 처리합니다.
  4. loginPage()에서 오류 및 로그아웃 메시지를 처리합니다.

  • 그런 다음 "LoginSecurityConfig\ 클래스를 개발하여 Spring 4 Security API를 사용하여 로그인 및 로그아웃 보안 기능을 제공합니다.\nLoginSecurityConfig.java

package com.journaldev.spring.secuity.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class LoginSecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	public void configureGlobal(AuthenticationManagerBuilder authenticationMgr) throws Exception {
		authenticationMgr.inMemoryAuthentication()
			.withUser("journaldev")
			.password("jd@123")
			.authorities("ROLE_USER");
	}
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()
			.antMatchers("/homePage").access("hasRole('ROLE_USER')")
			.and()
				.formLogin().loginPage("/loginPage")
				.defaultSuccessUrl("/homePage")
				.failureUrl("/loginPage?error")
				.usernameParameter("username").passwordParameter("password")				
			.and()
				.logout().logoutSuccessUrl("/loginPage?logout"); 
		
	}
}

코드 설명:- 사용자 자격 증명을 저장 및 관리하고 로그인 및 로그아웃 보안 기능을 처리하기 위해 "LoginSecurityConfig\에 두 가지 방법을 정의했습니다.

  1. @EnableWebSecurity 주석은 모든 웹 애플리케이션에서 웹 보안을 활성화하는 데 사용됩니다.
  2. @EnableWebMVCSecurity Annotation은 Spring MVC 기반 웹 애플리케이션에서 웹 보안을 활성화하는 데 사용됩니다.\n참고:- @EnableWebMVCSecurity 주석은 Spring 4.x Framework.4에서 더 이상 사용되지 않습니다. "LoginSecurityConfig\ 클래스 또는 Spring Security를 구성하도록 지정된 모든 클래스는 "WebSecurityConfigurerAdapter\ 클래스를 확장하거나 관련 인터페이스를 구현해야 합니다.
  3. configureGlobal() 메서드는 사용자 자격 증명을 저장하고 관리하는 데 사용됩니다.
  4. configureGlobal() 메소드에서 우리는 권한() 메소드를 사용하여 "ROLE_USER\와 같은 애플리케이션 역할을 정의할 수 있습니다. 동일한 목적으로 roles() 메소드도 사용할 수 있습니다.
  5. authority()와 roles() 메소드의 차이점:
  6. authorities()에는 "ROLE_USER\와 같은 완전한 역할 이름이 필요합니다. roles()에는 "USER\와 같은 역할 이름이 필요합니다. 자동으로 "ROLE_\ 값을 이 "USER\ 역할 이름에 추가합니다. 참고:- 다음 게시물에서 "USER”,"ADMIN”과 같은 역할을 시연하기 위해 또 다른 예를 개발할 것입니다.
  7. 로그인 및 로그아웃 보안을 관리하는 중요한 방법은 configure(HttpSecurity http)입니다.
  8. 다음 코드는 "/homePage”에 대한 무단 액세스를 방지하기 위해 사용됩니다. 이 페이지에 직접 액세스를 시도하면 자동으로 "/loginPage” 페이지로 리디렉션됩니다.

.antMatchers("/homePage").access("hasRole('ROLE_USER')")

access("hasRole('ROLE_USER')”) 메서드 호출을 제거하면 애플리케이션에 로그인하지 않고도 이 페이지에 액세스할 수 있습니다.13. formLogin() 및 logout() 메서드를 사용하여 로그인 및 로그아웃 기능을 구성했습니다.

  • Spring MVC 구성 활성화\nLoginApplicationConfig.java

package com.journaldev.spring.secuity.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

@EnableWebMvc
@Configuration
@ComponentScan({ "com.journaldev.spring.*" })
@Import(value = { LoginSecurityConfig.class })
public class LoginApplicationConfig {
	@Bean
	public InternalResourceViewResolver viewResolver() {
		InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
		viewResolver.setViewClass(JstlView.class);
		viewResolver.setPrefix("/WEB-INF/views/");
		viewResolver.setSuffix(".jsp");
		return viewResolver;
	}
	
}

코드 설명:- "web.xml\ 파일 작성을 피하기 위해 "LoginApplicationConfig\ 클래스를 사용하여 Spring MVC View Resolver를 정의합니다.

  1. @EnableWebMvc 주석은 Spring Framework에서 Spring 웹 MVC 애플리케이션 기능을 활성화하는 데 사용됩니다.
  2. @Import Annotation은 Spring Security Configuration 클래스를 이 클래스로 가져오는 데 사용됩니다.
  3. context:component-scan” Spring XML 구성.

  • 스프링 보안 초기화

package com.journaldev.spring.secuity.config.core;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;

public class SpringSecurityInitializer extends AbstractSecurityWebApplicationInitializer {

}

"SpringSecurityInitializer\는 springSecurityFilterChain을 사용하기 위해 DelegatingFilterProxy를 등록하는 데 사용됩니다. web.xml 파일에 필터 구성을 작성하지 않습니다.- Spring MVC 애플리케이션 초기화

package com.journaldev.spring.secuity.config.core;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import com.journaldev.spring.secuity.config.LoginApplicationConfig;

public class SpringMVCWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

	@Override
	protected Class<?>[] getRootConfigClasses() {
		return new Class[] { LoginApplicationConfig.class };
	}

	@Override
	protected Class<?>[] getServletConfigClasses() {
		return null;
	}

	@Override
	protected String[] getServletMappings() {
		return new String[] { "/" };
	}
	
}

메모:-

  1. 애플리케이션에 액세스할 때 기본적으로 SpringMVCWebAppInitializer의 getServletMappings()는 루트 URL: "/”에 액세스하도록 허용합니다. 다른 URL로 전달하도록 재정의할 수 있습니다.
  2. Spring 또는 Pivotal 팀은 주석을 도입하여 이 많은 Java 코드를 피하기 위해 이 문제를 해결하고 있습니다. https://jira.spring.io/browse/SPR-10359에서 확인하세요.

  • welcomePage.jsp 파일 개발

<h3>Welcome to JournalDEV Tutorials</h3>
<a href="${pageContext.request.contextPath}/loginPage">Login to Journal</a>

  • loginPage.jsp 파일 개발

<%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core"%>
<html>
<body onload='document.loginForm.username.focus();'>
	<h3>JournalDEV Tutorials</h3>

	<c:if test="${not empty error}"><div>${error}</div></c:if>
	<c:if test="${not empty message}"><div>${message}</div></c:if>

	<form name='login' action="<c:url value='/loginPage' />" method='POST'>
		<table>
			<tr>
				<td>UserName:</td>
				<td><input type='text' name='username' value=''></td>
			</tr>
			<tr>
				<td>Password:</td>
				<td><input type='password' name='password' /></td>
			</tr>
			<tr>
				<td colspan='2'><input name="submit" type="submit" value="submit" /></td>
			</tr>
		</table>
		<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
	</form>
</body>
</html>

  • homepage.jsp 파일 개발

<%@taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core"%>
<h3>Welcome to JournalDEV Tutorials</h3>
<ul>
	<li>Java 8 tutorial</li>
	<li>Spring tutorial</li>
	<li>Gradle tutorial</li>
	<li>BigData tutorial</li>
</ul>

<c:url value="/logout" var="logoutUrl" />
<form id="logout" action="${logoutUrl}" method="post" >
  <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
<c:if test="${pageContext.request.userPrincipal.name != null}">
	<a href="javascript:document.getElementById('logout').submit()">Logout</a>
</c:if>

Spring Security MVC 로그인 로그아웃 예제 실행

이 Spring 웹 애플리케이션을 실행하려면 Servlet 3.1.0 Container를 사용하여 Spring 4 및 Java 8 환경을 지원하는 웹 컨테이너가 필요합니다.

참고:- 이 예를 관찰하면 web.xml 파일을 올바르게 사용하고 있지 않은 것입니다. Web Application이므로 Maven은 web.xml 파일을 검색하여 Application에서 찾지 못하면 일부 오류를 발생시킵니다. 그것은 Maven 관련 문제를 피하기 위해 pom.xml 파일에 "\ 플래그를 구성해야 합니다. Spring 4 Security Module Simple Example에 대한 모든 것입니다. 다음 게시물에서 더 실시간으로 유용한 예제를 개발할 것입니다. 역할 관리, Remember-Me 기능, WebSocket 보안 등 내 게시물이 마음에 들거나 문제/제안 사항이 있으면 댓글을 남겨주세요.