본문 바로가기

웹_프론트_백엔드/JAVA프레임윅기반_풀스택

2020.07.06

1. 2019년도 개발자 에코시스템의 현황 - Java

 : https://www.jetbrains.com/ko-kr/lp/devecosystem-2019/java/

 

 

2. 애플리케이션 테스트(프로젝트 수행 단계에 따른 테스트 분류)

1) 단위 테스트(Unit Test, 유닛 테스트)

 : 작은 소프트웨어 단위(컴포넌트 또는 모듈)를 테스트,

   일반적으로 개발자 자신에 의해 행해진다,

   과거에는 시간 부족을 이유로 단위 테스트가 생략되었으나 최근에는 개발 도구의 발전으로 

   개발 과정 중에 자동으로 진행된다,

   단위 테스트는 아주 중요한 부분이므로 개발 도구에서 지원하지 않아도 반드시 수행해야 한다.


2) 통합 테스트(Integration Test)

 : 모듈 사이의 인터페이스, 통합된 컴포넌트 간의 상호 작용을 테스트,

   하나의 프로세스가 완성된 경우 부분적으로 통합 테스트를 수행하는 경우도 있다.
   변경할수 없는 부분(외부 라이브러리 등)까지 묶어서 같이 테스트 할때 사용.


3) 시스템 테스트(System Test)

 : 통합된 단위 시스템의 기능이 시스템에서 정상적으로 수행되는지를 테스트,

   성능 및 장애 테스트가 여기에 포함


4) 인수 테스트(Acceptance Test)

 : 일반적으로 최종 사용자(client)와 업무에 따른 이해관계자 등이 테스트를 수행함으로써

   개발된 제품에 대해 운영 여부를 결정하는 테스트,

   실제 업무 적용 전에 수행한다.


3. 테스트 코드의 장점
1) 테스트 환경 셋팅 자동화


2) 통합 테스트 시간을 줄여준다.


3) 전체 테스트를 자동화해준다.  


4) 서비스를 안정적으로 운영할 수 있다.

 

 

4. TDD(Test-Driven Develpment)
 : 테스트를 먼저 만들고 테스트를 통과하기 위한 것을 짜는 것

 

 

5. javaProj2

1) Maven Project 생성

 : 우클릭 New > Other... 클릭

> Maven Project 클릭

> Use default Workspace location 선택 후 Next 클릭

> Filter에 maven-archetype-quick 검색, org.apache.maven.archetypes 선택 후 Next 클릭

> Group Id, Artifact Id, Package 입력 후 Finish 클릭

2) maven은 기본적으로 JUnit을 깔고 간다(실습은 JUnit 4.11로 진행)

3) 메이븐 설정 파일 pom.xml을 이용, java 1.8로 변경하기

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.mvn</groupId>
  <artifactId>javaProj2</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <name>javaProj2</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.7.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

 

** [src/main/java] com.mvn.javaproj2 > App.java

package com.mvn.javaproj2;

/**
 * Hello world!
 *
 */
public class App 
{
	public String getWelcome() {
		return "welcome";
	}
	
	public String getHello() {
		return "hello";
	}
	
	public String getBye() {
		return "bye";
	}
	
	
    public static void main( String[] args )
    {
        System.out.println( "안녕하세요 JUnit" );
        
        App app = new App();
        String welcome = app.getWelcome();
        String hello = app.getHello();
		String bye = app.getBye();
        
		// 위 메소드의 동작한 결과값을 검증하려면?
		if("Welcome".equals(welcome)) System.out.println(true);
		if("hello".equals(hello)) System.out.println(true);
		if("bye".equals(bye)) System.out.println(true);	
        
    }
}

 

** [src/test/java] com.mvn.javaproj2 > AppTest.java

package com.mvn.javaproj2;


import static org.junit.Assert.assertEquals;

import org.junit.Test;

//JUnit 으로 테스트 동작시킬 클래스와 메소드는 모두 public 으로 만들자.
public class AppTest {

	private App app = new App();
	
	@Test
	public void test1() {
//		if("welcome".equals(app.getWelcome())) {
//			System.out.println(true);
//		} else {
//			System.out.println(false);
//		}
		
		// assertXXX() 메소드 사용
		assertEquals("welcome", app.getWelcome());
		assertEquals("Hello", app.getHello());
		assertEquals("bye", app.getBye());
	}
	
	@Test
	public void test2() {
		assertEquals("Bye", app.getBye());
	}
	
	@Test
	public void test3() {
		assertEquals("hello", app.getHello());
	}
	
}

 

4) 프로젝트 단위로 테스트 진행

 : 프로젝트 선택 후 우클릭 > Run As > JUnit Test 클릭 (혹은 Ctrl + F11)

** 아래의 사진과 같이 출력됨(JUnit 4 버전은 작성한 순서대로 출력되지 않는다)

5) 메소드 단위로 테스트 진행

 : 메소드 이름 선택 후 우클릭 > Run As > JUnit Test 클릭 (혹은 Ctrl + F11)

** 아래의 사진과 같이 출력됨

6) JUnit Test Case 파일 생성

① 패키지 선택 후 우클릭 > New > JUnit Test Case 클릭

② 아래의 사진 참고하여 삼각형 모양의 도형 클릭 > JUnit Test Case 선택

7) 계산기 예제

** [src/main/java] com.mvn.javaproj2 > Calculator.java

package com.mvn.javaproj2;

public class Calculator {
	public int add(int a, int b) {
		return a + b;
	}
	public int sub(int a, int b) {
		return a - b;
	}
	public int mul(int a, int b) {
		return a * b;
	}
	public int div(int a, int b) {
		return a / b;
	}
}

 

** [src/test/java] com.mvn.javaproj2 > CalculatorTest.java

package com.mvn.javaproj2;

import static org.junit.Assert.*;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class CalculatorTest {

	// JUnit은 멤버 필드 방식을 비추한다 --> 테스트 결과가 다른 테스트 결과에 영향을 줄 수 있다.
	// 각각의 '테스트'는 '독립적'으로 실행되는 것을 보장한다.
	
	// 각 테스트 전/후에 공통으로 수행해야 할 코드가 필요하다면
	// @Before, @After
	//private Calculator cal = new Calculator();	// 비추
	
	private Calculator cal;
	
	@Before		// 테스트 메소드 실행 전에 수행할 메소드
	public void setUp() {
		System.out.println("[테스트 전]");
		cal = new Calculator();
	}
	
	@After		// 테스트 메소드 실행 후에 수행할 메소드
	public void shutDown() {
		System.out.println("[테스트 후]");
	}

	
	@Test
	public void testAdd() {
		System.out.println("testAdd()");
		int result = cal.add(10, 20);
		assertEquals(30, result);
	}
	
	@Test
	public void testSub() {
		System.out.println("testSub()");
		int result = cal.sub(10, 20);
		assertEquals(-10, result);
	}
	
	@Test
	public void testMul() {
		System.out.println("testMul()");
		int result = cal.mul(10, 20);
		assertEquals(200, result);
	}
	
	@Test
	public void testDiv() {
		System.out.println("testDiv()");
		int result = cal.div(10, 20);
		assertEquals(0, result);
	}

}

 

8) @Before, @After

 


6. 인증(Authentication)
 : 시스템 접근 시, 등록된 사용자인지 여부를 확인하는 것

   예) 로그인

 


7. 인가(Authorization)
 : 접근 후, 인증된 사용자에게 권한을 부여하는 것,
   권한에 따라 사용 가능한 기능이 제한됨
   예) 사용자 등급(일반/VIP/관리자)


8. Spring Projects

 : https://spring.io/projects/spring-security, 스프링 공식 홈페이지 설명

 

 

9. STS18_Security

** 메이븐 설정 파일, pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.lec</groupId>
	<artifactId>sts18_security</artifactId>
	<name>STS18_Security</name>
	<packaging>war</packaging>
	<version>1.0.0-BUILD-SNAPSHOT</version>
	<properties>
		<java-version>1.6</java-version>
		<org.springframework-version>5.2.1.RELEASE</org.springframework-version>
		<org.aspectj-version>1.6.10</org.aspectj-version>
		<org.slf4j-version>1.6.6</org.slf4j-version>
	</properties>
	<dependencies>
		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework-version}</version>
			<exclusions>
				<!-- Exclude Commons Logging in favor of SLF4j -->
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				 </exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
				
		<!-- AspectJ -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>${org.aspectj-version}</version>
		</dependency>	
		
		<!-- Logging -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${org.slf4j-version}</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>jcl-over-slf4j</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.15</version>
			<exclusions>
				<exclusion>
					<groupId>javax.mail</groupId>
					<artifactId>mail</artifactId>
				</exclusion>
				<exclusion>
					<groupId>javax.jms</groupId>
					<artifactId>jms</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jdmk</groupId>
					<artifactId>jmxtools</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jmx</groupId>
					<artifactId>jmxri</artifactId>
				</exclusion>
			</exclusions>
			<scope>runtime</scope>
		</dependency>

		<!-- @Inject -->
		<dependency>
			<groupId>javax.inject</groupId>
			<artifactId>javax.inject</artifactId>
			<version>1</version>
		</dependency>
				
		<!-- Servlet -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>jsp-api</artifactId>
			<version>2.1</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
	
		<!-- Test -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.7</version>
			<scope>test</scope>
		</dependency>
		
		
		
		<!-- Security -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-core</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-taglibs</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>


		        
	</dependencies>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-eclipse-plugin</artifactId>
                <version>2.9</version>
                <configuration>
                    <additionalProjectnatures>
                        <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
                    </additionalProjectnatures>
                    <additionalBuildcommands>
                        <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
                    </additionalBuildcommands>
                    <downloadSources>true</downloadSources>
                    <downloadJavadocs>true</downloadJavadocs>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <compilerArgument>-Xlint:all</compilerArgument>
                    <showWarnings>true</showWarnings>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <configuration>
                    <mainClass>org.test.int1.Main</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

 

** 메이븐 설정을 통해 정상적으로 다운로드되면 아래의 사진과 같이 5개의 jar 파일이 다운된다.

** src > main > webapp > WEB-INF > web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			/WEB-INF/spring/root-context.xml
			/WEB-INF/spring/appServlet/security-context.xml
		</param-value>
	</context-param>
	
	<!-- Creates the Spring Container shared by all Servlets and Filters -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Processes application requests -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	
	
	<!-- 스프링 컨테이너 인코딩 설정 -->
	<filter>
		<filter-name>encodingFilter</filter-name>
		<filter-class>
			org.springframework.web.filter.CharacterEncodingFilter     
		</filter-class>
		<init-param>
			<param-name>encoding</param-name>   
			<param-value>UTF-8</param-value>
		</init-param>
		<init-param>
			<param-name>forceEncoding</param-name>  
			<param-value>true</param-value>
		</init-param>
	</filter>    

	<filter-mapping>
		<filter-name>encodingFilter</filter-name>
		<url-pattern>/*</url-pattern>                 
	</filter-mapping>


	<!-- Security 관련 filter 추가 -->
	<filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>


</web-app>

 

** src > main > webapp > WEB-INF > spring > appServlet > security-context.xml

<?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">
		
	<bean id="customAccessDenied"
		class="com.lec.sts18_security.security.CustomAccessDeniedHandler"/>
		
	<bean id="customLoginSuccess"
		class="com.lec.sts18_security.security.CustomLoginSuccessHandler"/>
		
	<!-- 컨테이너의 HTTP security 요소 -->
	<security:http>
		<!-- 특정 url pattern 의 요청이 들어올때 인터셉터를 이용해 접근 제한 설정 -->
		<security:intercept-url pattern="/sample/all" access="permitAll"/>
		
		<!-- /sample/member URI 요청은 ROLE_MEMBER 라는 권한이 있는 사용자만 접근 가능 -->
		<security:intercept-url pattern="/sample/member" access="hasRole('ROLE_MEMBER')"/>
		
		<!-- /sample/admin URI 요청은 ROLE_ADMIN 라는 권한이 있는 사용자만 접근 가능 -->
		<security:intercept-url pattern="/sample/admin" access="hasRole('ROLE_ADMIN')"/>
		
		<!-- login 페이지 -->
		<!-- <security:form-login/>-->	<!-- 스프링에서 기본 제공하는 로그인 페이지 사용 -->
		<security:form-login login-page="/customLogin"
			authentication-success-handler-ref="customLoginSuccess"/>
		
		<!-- 접근 제한 메시지 처리 -->
		<!-- 
		<security:access-denied-handler error-page="/accessError"/>
		-->
		<security:access-denied-handler ref="customAccessDenied"/>
		
		<!-- 로그아웃 처리 -->
		<security:logout logout-url="/customLogout" invalidate-session="true"/>
		
	</security:http>
	
	<!-- AuthenticationManager 빈 생성, 
		  인증  (예) 로그인 -->
	<security:authentication-manager>
		<!-- UserDetailsService 사용자 인증과 권한 처리 -->
		<security:authentication-provider>
			<security:user-service>
				<security:user name="member" password="{noop}member" authorities="ROLE_MEMBER"/>
				<security:user name="admin" password="{noop}admin" authorities="ROLE_MEMBER, ROLE_ADMIN"/>
			</security:user-service>
		</security:authentication-provider>
	
	</security:authentication-manager>		

</beans>

 

** security-context.xml의 Namespaces 설정

** [src/main/java] com.lec.sts18_security > SampleController.java

package com.lec.sts18_security;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/sample/*")
public class SampleController {
	
	//@RequestMapping(value = "/all", method=RequestMethod.GET) 의 축약형	
	@GetMapping("/all")
	public void doAll() {  // 리턴타입 없으면 url 과 같은 경로의 jsp 파일을 찾는다.--> /sample/all.jsp
		System.out.println("doAll() : access everybody");
	}
	
	@GetMapping("/member")
	public void doMember() {
		System.out.println("doMember() : access member only");
	}
	
	@GetMapping("/admin")
	public void doAdmin() {
		System.out.println("doAdmin() : access admin only");
	}
	
}


** src > main > webapp > WEB-INF > View > sample > admin.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>admin</title>
</head>
<body>
<h1>/sample/admin page</h1>

<a href="${pageContext.request.contextPath }/customLogout">Logout</a>

</body>
</html>


** src > main > webapp > WEB-INF > View > sample > all.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>all</title>
</head>
<body>
<h1>/sample/all page</h1>

</body>
</html>


** src > main > webapp > WEB-INF > View > sample > member.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>member</title>
</head>
<body>
<h1>/sample/member page</h1>

</body>
</html>

 

** [src/main/java] com.lec.sts18_security > CommonController.java

package com.lec.sts18_security;

import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

@Controller
public class CommonController {
	@GetMapping("/accessError")
	public void accessDenied(Authentication auth, Model model) {
		System.out.println("access Denied : " + auth);
		model.addAttribute("msg", "접근 권한 거부");
	}
	
	@GetMapping("/customLogin")
	public void loginInput(String error, String logout, Model model) {
		System.out.println("error: " + error);
		System.out.println("logout: " + logout);
		
		if(error != null) {
			model.addAttribute("error", "Login Error Check Your Account");
		}
		
		if(logout != null) {
			model.addAttribute("logout", "Logout!!");
		}
		
	}
	
	@GetMapping("/customLogout")
	public void logoutGET() {
		System.out.println("custom logout");
	}
	
	@PostMapping("/customLogout")
	public void logoutPost() {
		System.out.println("post custom logout");
	}
	
}

 

** src > main > webapp > WEB-INF > View > accessError.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="sec" %>

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Access Denied Page</title>
</head>
<body>
<h1>Access Denied Page</h1>
<h2><c:out value="${SPRING_SECURITY_403_EXCEPTION.getMessage() }"/></h2>
<h2><c:out value="${msg }"/></h2>
</body>
</html>

 

** [src/main/java] com.lec.sts18_security.security > CustomAccessDeniedHandler.java

package com.lec.sts18_security.security;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;

public class CustomAccessDeniedHandler implements AccessDeniedHandler {
	
	// request, response 를 매개변수로 받기 때문에, 서블릿 API 직접 이용하여 handle 가능.
	@Override
	public void handle(HttpServletRequest request, HttpServletResponse response,
			AccessDeniedException accessDeniedException) throws IOException, ServletException {
		System.out.println("Access Denied Handler");
		System.out.println("redirect 합니다");
		response.sendRedirect(request.getContextPath() + "/accessError");

	}
	
}

 

** src > main > webapp > WEB-INF > View > 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>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>로그인페이지</title>
</head>
<body>
  <h1>Custom Login Page</h1>
  <h2><c:out value="${error}"/></h2>
  <h2><c:out value="${logout}"/></h2>
  
  <form method='post' action="${pageContext.request.contextPath}/login">
    <input type='text' name='username' value='admin'><br>
    <input type='password' name='password' value='admin'><br>
    <input type='checkbox' name='remember-me'> Remember Me <br>
    <input type='submit'><br>
    <input type="hidden" name="${_csrf.parameterName }" value="${_csrf.token }" />  
  </form>
  
</body>
</html>

 

** <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>

** [src/main/java] com.lec.sts18_security.security > CustomLoginSuccessHandler.java

package com.lec.sts18_security.security;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

public class CustomLoginSuccessHandler implements AuthenticationSuccessHandler {

	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
			Authentication authentication) throws IOException, ServletException {
		
		System.out.println("Login Success");
		
		// Authentication 객체를 이용하여 사용자가 가진 모든 권한을 문자열로 체크 가능
		
		List<String> roleNames = new ArrayList<String>();
		authentication.getAuthorities().forEach(authority -> {
			roleNames.add(authority.getAuthority());
		});
		
		System.out.println("ROLE NAMES: " + roleNames);
		
		// 로그인한 사용자가 ROLE_ADMIN 권한을 가졌다면 로그인 후 곧바로 /sample/admin 으로 이동
		if(roleNames.contains("ROLE_ADMIN")) {
			response.sendRedirect(request.getContextPath() + "/sample/admin");
			return;
		}
		
		// 아니면 /sample/member 로 이동
		if(roleNames.contains("ROLE_MEMBER")) {
			response.sendRedirect(request.getContextPath() + "/sample/member");
			return;
		}
		
		response.sendRedirect(request.getContextPath());

	} // end onAuthenticationSuccess()

} // end CustomLoginSuccessHandler

 

** src > main > webapp > WEB-INF > View > customLogout.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>로그아웃</title>
</head>
<body>
<h1> Logout Page</h1>
<form action="${pageContext.request.contextPath}/customLogout" method='post'>
<input type="hidden"name="${_csrf.parameterName}"value="${_csrf.token}"/>
<button>로그아웃</button>
</form>
</body>
</html>

'웹_프론트_백엔드 > JAVA프레임윅기반_풀스택' 카테고리의 다른 글

애플리케이션_테스트 시험(제출 코드와 풀이)  (0) 2020.07.07
2020.07.07  (0) 2020.07.07
2020.07.06  (0) 2020.07.06
2020.07.03  (0) 2020.07.03
2020.07.02  (0) 2020.07.02