스프링 시큐리티 역할 기반 접근 권한 예제

오늘은 스프링 시큐리티 롤 기반의 접근과 권한 예제를 살펴보겠습니다. 그러나 이 글을 읽기 전에 “스프링 4 시큐리티 MVC 로그인 로그아웃 예제”에 대한 이전 글을 읽어 기본적인 스프링 4 시큐리티에 대한 지식을 습득해 주세요.

스프링 시큐리티 롤

이 글에서는 스프링 웹 애플리케이션에서 “USER”, “ADMIN”과 같은 스프링 시큐리티 롤을 어떻게 정의, 사용 및 관리하는지에 대해 논의하겠습니다. 이전 글과 마찬가지로 이 예제는 In-Memory Store 및 스프링 자바 구성 기능을 사용하여 Spring 4 MVC Security를 사용합니다. 즉, web.xml 파일을 사용하지 않고 Spring XML 구성을 작성하지 않습니다. 우리는 “In-Memory Store” 옵션을 사용하여 사용자 자격 증명을 저장하고 관리할 것입니다. 이 예제를 개발하기 위해 Spring 4.0.2.RELEASE, Spring STS 3.7 Suite IDE, Spring TC Server 3.1 및 Java 1.8, Maven 빌드 도구를 사용할 것입니다.

스프링 시큐리티 롤 기반의 접근과 권한 예제

  1. Spring STS Suite에서 “Simple Spring Web Maven” 프로젝트를 다음과 같은 세부 사항으로 생성하십시오.
    프로젝트 이름 : SpringMVCSecruityMavenRolesApp2. 이전 게시물에서 사용한 pom.xml 파일을 동일하게 사용하되 다음과 같이 변경 사항을 적용하십시오.
<artifactId>SpringMVCSecruityMavenRolesApp</artifactId>

<build>
  <finalName>SpringMVCSecruityMavenRolesApp</finalName>
</build>
</project>
  1. 이전 게시물의 모든 Java 및 JSP 파일을 사용하십시오. 여기에서는 업데이트 된 내용 또는 새로 추가된 내용에 대해서만 논의할 것입니다.
  2. LoginSecurityConfig.java 파일을 업데이트하여 “USER” 및 “ADMIN”과 같은 사용자 역할을 구성하십시오.
    LoginSecurityConfig.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("jduser").password("jdu@123").authorities("ROLE_USER")
			.and()
			.withUser("jdadmin").password("jda@123").authorities("ROLE_USER","ROLE_ADMIN");
	}
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {

		
		http.authorizeRequests()
			.antMatchers("/homePage").access("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")
			.antMatchers("/userPage").access("hasRole('ROLE_USER')")
			.antMatchers("/adminPage").access("hasRole('ROLE_ADMIN')")
			.and()
				.formLogin().loginPage("/loginPage")
				.defaultSuccessUrl("/homePage")
				.failureUrl("/loginPage?error")
				.usernameParameter("username").passwordParameter("password")				
			.and()
				.logout().logoutSuccessUrl("/loginPage?logout"); 
		
	}
}

코드 설명

  1. configureGlobal() 메소드에서 두 개의 사용자를 추가했습니다. “ROLE_USER” 역할을 갖는 사용자와 “ROLE_USER” 및 “ROLE_ADMIN” 역할을 모두 갖는 다른 사용자입니다. 이 두 번째 사용자는 관리자 사용자로 작동합니다. 이와 같이 우리는 어떤 수의 사용자와 역할을 구성할 수 있습니다.
  2. 응용 프로그램에서 역할을 구성하기 위해 authorities(ROLE) 또는 roles(ROLE) 메소드를 사용할 수 있습니다.
  3. authorities()와 roles() 메소드의 차이점 :
  • authorities()는 “ROLE_USER”와 같은 완전한 역할 이름이 필요합니다.
  • roles()는 “USER”와 같은 역할 이름이 필요합니다. 자동으로 이 “USER” 역할 이름에 “ROLE_” 값을 추가합니다.
  1. configure() 메소드에서는 필요한 액세스 역할이 있는 다른 URL을 정의했습니다.
antMatchers("/homePage")
   .access("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")

이 코드 스니펫은 “homePage”가 USER 및 ADMIN 역할에 모두 사용 가능하도록 구성합니다.

 .antMatchers("/userPage").access("hasRole('ROLE_USER')")
 .antMatchers("/adminPage").access("hasRole('ROLE_ADMIN')")

이 코드 스니펫은 “userPage”가 “USER” 역할에만 접근 가능하도록 구성하고 “adminPage”가 “ADMIN” 역할에만 접근 가능하도록 구성합니다. 다른 역할이 이러한 페이지에 액세스하면 “403 액세스가 거부되었습니다.” 오류 메시지가 표시됩니다.

  1. 아래와 같이 새로운 URL 액세스 경로를 정의하도록 LoginController.java 컨트롤러 파일을 업데이트하십시오.
    LoginController.java
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 = {"/userPage"}, method = RequestMethod.GET)
	public ModelAndView userPage() {
		ModelAndView model = new ModelAndView();
		model.setViewName("userPage");
		return model;
	}
	
	@RequestMapping(value = {"/adminPage"}, method = RequestMethod.GET)
	public ModelAndView adminPage() {
		ModelAndView model = new ModelAndView();
		model.setViewName("adminPage");
		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;
	}

}

코드 설명 이전 포스트 예제에 추가로 두 개의 새로운 URL을 추가했습니다.

  1. “/userPage”는 USER 역할이 정상 사용자 활동을 액세스하고 수행하는 데 사용됩니다.

  2. “/adminPage”는 ADMIN 역할이 관리자 사용자 활동을 액세스하고 수행하는 데 사용됩니다. ADMIN 역할은 “/userPage” URL에도 액세스할 수 있습니다.

  3. 사용자 및 관리자 역할별 활동을 제공하기 위해 homePage.jsp 파일을 업데이트했습니다.
    homePage.jsp

<%@taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core"%>
<a href="${pageContext.request.contextPath}/userPage">JD User</a> | <a href="${pageContext.request.contextPath}/adminPage">JD Admin</a> | <a href="javascript:document.getElementById('logout').submit()">Logout</a>

<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>

여기에 상단 프레임에 세 가지 메뉴 옵션을 추가했습니다. “로그아웃”은 이전 포스트에서 설명되었습니다. 새로운 두 개의 링크는 다음과 같습니다:

  1. JD 사용자: “USER” 및 “ADMIN” 역할 모두에서 액세스 가능
  2. JD 관리자: “ADMIN” 역할에서만 액세스 가능

참고:- 실시간 애플리케이션에서는 “USER” 역할에만 “JD 사용자” 링크를 표시하고 “JD 관리자” 링크를 숨깁니다. “USER” 역할에서 액세스 가능한지 여부를 테스트하고 정확한 오류 메시지를 확인하기 위해 이 링크를 숨기지 않았습니다. 20. “ADMIN” 역할의 홈페이지로 작동하는 새로운 adminPage.jsp 파일을 추가하십시오.
adminPage.jsp

<%@taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core"%>
<h3>Welcome to JournalDEV Tutorials</h3>
<h3>Admin Page</h3>

<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>
  1. “USER” 역할을 위한 새로운 userPage.jsp 파일을 추가합니다.
    userPage.jsp
<%@taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core"%>
<h3>Welcome to JournalDEV Tutorials</h3>
<h3>User Page</h3>

<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>

우리는 애플리케이션 개발을 완료했습니다. 이제 프로젝트의 최종 구조를 확인하고 애플리케이션을 테스트할 시간입니다.26. 최종 프로젝트 구조는 다음과 같습니다:

Spring Security Roles 예제 애플리케이션 테스트

  1. 스프링 STS IDE에서 프로젝트를 마우스 오른쪽 버튼으로 클릭하고 “Run AS >> Run on Server” 옵션을 선택합니다. 아래에 표시된 대로 기본 응용 프로그램 환영 페이지에 액세스됩니다. 3. “Login to JournalDEV” 링크를 클릭합니다. 이제 로그인 페이지에 있습니다. 5. “USER” 역할 자격 증명으로 첫 번째로 로그인합니다. 사용자 이름: jduser 비밀번호: jdu@123 이제 3개의 메뉴 옵션인 “JD User”, “JD Admin” 및 “Logout”이 있는 응용 프로그램 홈페이지를 볼 수 있습니다. “JD User” 링크를 클릭합니다. “USER” 역할 자격 증명을 사용하여 응용 프로그램에 로그인했기 때문에 아래에 표시된 대로이 링크에 액세스 할 수 있습니다. 스프링 STS IDE에서 뒤로 가기 화살표를 사용하고 이번에는 “JD Admin” 링크를 클릭합니다. “USER” 역할 자격 증명으로 로그인했기 때문에이 링크에 액세스 할 수 없습니다. 그래서 “403 Access is denied”라는 오류 메시지를 보았습니다. 9. 이제 ADMIN 역할 자격 증명으로 로그인 한 다음 “JD Admin” 링크에 액세스 할 수 있습니다. “Logout” 링크를 테스트하여 응용 프로그램에서 로그 아웃합니다.

{
“error”: “Upstream error…”
}

Source:
https://www.digitalocean.com/community/tutorials/spring-security-role-based-access-authorization-example