[어제 배운 Spring Security에 spring-jdbc 설정 추가하기]
1. DataSource가 필요
① 메이븐 설정 파일 pom.xml에 jdbc 라이브러리 추가
<?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>
<!-- Maven 빌드를 사용하는 Spring 에서 오라클 라이브러리 추가하기 -->
<!--dependencies 위에 설정 -->
<repositories>
<repository>
<id>oracle</id>
<name>ORACLE JDBC Repository</name>
<url>https://code.lds.org/nexus/content/groups/main-repo</url>
</repository>
</repositories>
<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 안쪽 에 설정 -->
<!-- ojdbc6 -->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.3</version>
</dependency>
<!-- spring jdbc 사용 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</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>
② spring-jdbc 설정 추가
** src > main > webapp > WEB-INF > spring > root-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:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<!-- spring-jdbc 빈 객체 생성 -->
<!-- DataSource 객체 -->
<beans:bean name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<beans:property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<beans:property name="url" value="jdbc:oracle:thin:@localhost:1521:XE"/>
<beans:property name="username" value="scott0316"/>
<beans:property name="password" value="tiger0316"/>
</beans:bean>
</beans>
2. JDBC를 이용한 인증/권한 체크 방식
방식1. spring에서 지정된 형식의 테이블 생성하는 방식
방식2. 기존에 작성된 데이터 베이스를 이용하는 방식
3. [방법1] spring-security 형식의 테이블 작성
1) 테이블 생성
** ERD > spring_security_oracle.erm
** ERD > spring_security_oracle.sql
/* Drop Tables */
DROP TABLE authorities CASCADE CONSTRAINTS;
DROP TABLE users CASCADE CONSTRAINTS;
/* Create Tables */
CREATE TABLE users(
username varchar2(50) NOT NULL,
password varchar2(50) NOT NULL,
enabled char(1) DEFAULT '1',
PRIMARY KEY (username)
);
CREATE TABLE authorities(
username varchar2(50) REFERENCES users(username),
authority varchar2(50) NOT NULL,
PRIMARY KEY (username, authority) -- 복합키
);
/* 데이터 DML */
INSERT INTO users (username, password) VALUES ('user00', '1234');
INSERT INTO users (username, password) VALUES ('member00', '1234');
INSERT INTO users (username, password) VALUES ('admin00', '1234');
INSERT INTO authorities VALUES ('user00', 'ROLE_USER');
INSERT INTO authorities VALUES ('member00', 'ROLE_MEMBER');
INSERT INTO authorities VALUES ('admin00', 'ROLE_MEMBER');
INSERT INTO authorities VALUES ('admin00', 'ROLE_ADMIN');
-- 확인
SELECT u.username, u.password ,u.enabled, a.authority
FROM users u, authorities a
WHERE u.username = a.username;
2) PasswordEncoder 문제 해결(spring-security 5부터는 반드시 PasswordEncoder를 지정 필요)
** [src/main/java] com.lec.sts18_security.security > CustomNoOpPasswordEncoder.java
package com.lec.sts18_security.security;
import org.springframework.security.crypto.password.PasswordEncoder;
public class CustomNoOpPasswordEncoder implements PasswordEncoder {
// 주어진 rawPassword를 인코딩하여 리턴, 일반적으로 SHA-1 혹은 그 이상의 암호화 알고리즘 사용
@Override
public String encode(CharSequence rawPassword) {
System.out.println("encode 전 : " + rawPassword);
return rawPassword.toString();
}
// 주어진 rawPassword가 인코딩된 비번과 동일한지 판정
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
System.out.println("matches 수행 : " + rawPassword + "::" + encodedPassword);
return rawPassword.toString().equals(encodedPassword);
}
}
** 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"/>
<bean id="customPasswordEncoder"
class="com.lec.sts18_security.security.CustomNoOpPasswordEncoder"/>
<!-- 컨테이너의 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>
<!-- InMemory 방식
<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>
-->
<!-- JDBC 사용 -->
<security:jdbc-user-service data-source-ref="dataSource"/>
<!-- PasswordEncoder 설정 -->
<security:password-encoder ref="customPasswordEncoder"/>
</security:authentication-provider>
</security:authentication-manager>
</beans>
4. [방법2] 기존에 작성된 데이터 베이스를 이용하는 방식
: 기존에 회원 관리 테이블이 있다면,
spring-security에서 지정한 결과를 반환하는 쿼리를 작성해 주는 작업으로도 처리가 가능
<security:jdbc-user-service> 태그에 users-by-username-query, authorities-by-username-query 속성 지정 가능
1) 사용자, 권한 테이블 생성
** ERD > test_auth_oracle.erm
** ERD > test_auth_oracle.sql
/* Drop Tables */
DROP TABLE tbl_member_auth CASCADE CONSTRAINTS;
DROP TABLE tbl_member CASCADE CONSTRAINTS;
/* Create Tables */
CREATE TABLE tbl_member (
userid varchar2(50) NOT NULL PRIMARY KEY,
userpw varchar2(100) NOT NULL,
username varchar2(100) NOT NULL,
regdate date DEFAULT SYSDATE,
updatedate date DEFAULT SYSDATE,
enabled char(1) DEFAULT '1'
);
CREATE TABLE tbl_member_auth (
userid varchar2(50) NOT NULL,
auth varchar2(50) NOT NULL,
CONSTRAINT fk_member_auth FOREIGN KEY(userid) REFERENCES tbl_member(userid),
PRIMARY KEY(userid, auth) -- 복합키
);
-- 확인
SELECT u.userid, u.userpw, u.enabled, a.auth
FROM tbl_member u, tbl_member_auth a
WHERE u.userid = a.userid;
-- 삭제
DELETE FROM tbl_member;
DELETE FROM TBL_MEMBER_AUTH;
-- 특정 user
SELECT u.userid, u.userpw, u.enabled, a.auth
FROM tbl_member u, tbl_member_auth a
WHERE u.userid = a.userid AND u.userid = 'admin90';
2) 메이븐 설정 파일 pom.xml을 통해 junit, hamcrest 라이브러리 추가
<?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>
<!-- Maven 빌드를 사용하는 Spring 에서 오라클 라이브러리 추가하기 -->
<!--dependencies 위에 설정 -->
<repositories>
<repository>
<id>oracle</id>
<name>ORACLE JDBC Repository</name>
<url>https://code.lds.org/nexus/content/groups/main-repo</url>
</repository>
</repositories>
<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.12</version>
<scope>test</scope>
</dependency>
<!-- ham, test 추가 -->
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework-version}</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 안쪽 에 설정 -->
<!-- ojdbc6 -->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.3</version>
</dependency>
<!-- spring jdbc 사용 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</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>
[추가] https://mvnrepository.com를 이용, hamcrest 라이브러리 추가
[추가] https://mvnrepository.com를 이용, spring test 라이브러리 추가
** 정상적으로 라이브러리가 추가되면 아래의 사진과 같이 확인됨
3) BCryptPasswordEncoder 암호화 처리
: bcrypt는 대표적인 암호 인코딩 전용 해시 함수,
특정 패스워드 암호화, 암호화된 패스워드 체크 가능, 역으로 원래 패스워드로는 못 돌림
** [src/main/java] com.lec.sts18_security.security > CustomNoOpPasswordEncoder.java
package com.lec.sts18_security.security;
import org.springframework.security.crypto.password.PasswordEncoder;
public class CustomNoOpPasswordEncoder implements PasswordEncoder {
// 주어진 rawPassword를 인코딩하여 리턴, 일반적으로 SHA-1 혹은 그 이상의 암호화 알고리즘 사용
@Override
public String encode(CharSequence rawPassword) {
System.out.println("encode 전 : " + rawPassword);
return rawPassword.toString();
}
// 주어진 rawPassword가 인코딩된 비번과 동일한지 판정
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
System.out.println("matches 수행 : " + rawPassword + "::" + encodedPassword);
return rawPassword.toString().equals(encodedPassword);
}
}
4) 인코딩된 패스워드 가진 사용자 추가
: BCryptPasswordEncoder을 이용, 패스워드 암호화된 사용자들을 추가하는 테스트 코드를 작성
** [src/test/java] com.lec.sts18_security > MemberTests.java
package com.lec.sts18_security;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.junit.*;
import org.junit.Before;
import org.junit.runner.*;
import org.junit.runners.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/*
* 스프링에서는 자동으로 클래스 간 여러 의존주입이 발생하기 때문에
* 다른 클래스에서 작성한 코드들을 사용할 수 있지만, JUnit 은 테스트 케이스 부분만 실행하기 때문에
* 빈 자동 등록이나 의존주입이 일어나지 않습니다.
* 따라서! @Service 나 @Mapper 가 붙은 클래스난 인터페이스도 쓰지 못하게 됩니다.
* 이럴때는
* @RunWith와 @ContextConfiguration을 이용합니다
*
* 위와 같이 하면 JUnit 테스트를 실행할때
* @RunWith의 SpringJUnit4ClassRunner 클래스가
* @ContextConfiguration에 적어 놓은 파일들을 같이 실행시킵니다.
* root-context.xml과 security-context.xml을 실행시켜 빈 등록과 의존 주입을 실행시키는 것입니다
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({
"file:src/main/webapp/WEB-INF/spring/root-context.xml",
"file:src/main/webapp/WEB-INF/spring/appServlet/security-context.xml"
})
// 메소드 이름 순으로 테스트 진행되는 어노테이션
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class MemberTests {
// 자동 주입받을 PasswordEncoder와 DataSource 객체
private PasswordEncoder pwencoder;
private DataSource ds;
public final PasswordEncoder getPwencoder() {return pwencoder;}
@Autowired
public final void setPwencoder(PasswordEncoder pwencoder) {this.pwencoder = pwencoder;}
public final DataSource getDs() {return ds;}
@Autowired
public final void setDs(DataSource ds) {this.ds = ds;}
Connection conn = null;
PreparedStatement pstmt = null;
final String SQL_INSERT_MEMBER
= "INSERT INTO tbl_member(userid, userpw, username) VALUES(?, ?, ?)";
final String SQL_INSERT_AUTH
= "INSERT INTO tbl_member_auth(userid, auth) VALUES(?, ?)";
@Before
public void initialize() {
System.out.println("MemberTests 시작");
try {
conn = ds.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
}
@After
public void finalize() {
System.out.println("MemberTests 종료");
try {
if(conn != null) {
conn.close();
conn = null;
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void testA() {
System.out.println("testA() 실행");
if(conn == null) {return;}
int cnt = 0;
String userid = "", userpw = "", username = "";
try {
pstmt = conn.prepareStatement(SQL_INSERT_MEMBER);
// 100명의 테스트용 데이터 생성
for(int i = 0; i < 100; i++) {
userpw = "pw" + i; // 패스워드 pw0, pw1, ... 생성
// 일반사용자: 운영자: 관리자 80:10:10 명 생성
if(i < 80) {
userid = "user" + i;
username = "일반사용자" + i;
} else if (i < 90) {
userid = "member" + i;
username = "회원" + i;
} else {
userid = "admin" + i;
username = "관리자" + i;
}
cnt = 0;
try {
pstmt.setString(1, userid);
pstmt.setString(2, pwencoder.encode(userpw)); // 패스워드 인코딩
pstmt.setString(3, username);
cnt = pstmt.executeUpdate();
} catch(Exception e) {
System.out.println(e.getMessage());
}
if(cnt > 0) {
System.out.println("INSERT_MEMBER 성공]" + userid + ":" + userpw + ":" + username);
} else {
System.out.println("INSERT_MEMBER 실패]" + userid + ":" + userpw + ":" + username);
}
} // end for
} catch(Exception e) {
e.printStackTrace();
} finally {
try {
if(pstmt != null) {
pstmt.close();
pstmt = null;
}
} catch(Exception e) {
e.printStackTrace();
}
}
} // end testA()
@Test
public void testB() {
System.out.println("testB() 실행");
if(conn == null) {return;}
int cnt = 0;
String userid = "", auth = "";
try {
pstmt = conn.prepareStatement(SQL_INSERT_AUTH);
for(int i = 0; i < 100; i++) {
if(i < 80) {
userid = "user" + i;
auth = "ROLE_USER";
} else if(i < 90) {
userid = "member" + i;
auth = "ROLE_MEMBER";
} else {
userid = "admin" + i;
auth = "ROLE_ADMIN";
}
cnt = 0;
try {
pstmt.setString(1, userid);
pstmt.setString(2, auth);
cnt = pstmt.executeUpdate();
if(cnt > 0) {
System.out.println("INSERT_AUTH 성공] " + userid + ":" + auth);
} else {
System.out.println("INSERT_AUTH 실패] " + userid + ":" + auth);
}
// admin 의 경우 ROLE_MEMBER 도 추가
if(userid.startsWith("admin")) {
auth = "ROLE_MEMBER";
pstmt.setString(1, userid);
pstmt.setString(2, auth);
cnt = pstmt.executeUpdate();
if(cnt > 0) {
System.out.println("INSERT_AUTH 성공] " + userid + ":" + auth);
} else {
System.out.println("INSERT_AUTH 실패] " + userid + ":" + auth);
}
}
} catch(Exception e) {
System.out.println(e.getMessage());
}
} // end for
} catch(Exception e) {
e.printStackTrace();
} finally {
try {
if(pstmt != null) {
pstmt.close();
pstmt = null;
}
} catch(Exception e) {
e.printStackTrace();
}
}
} // end testB()
} // end TEST
** MemberTests.java 결과값
5. javaProj2
** [src/test/java] com.mvn.javaproj2 > TestJunit1.java
package com.mvn.javaproj2;
import static org.junit.Assert.*;
import org.junit.Test;
/*
* 1. void assertEquals(boolean expected, boolean actual)
* 2. void assertFalse(boolean condition) // false 인지 체크
* 3. void assertNotNull(Object object) // Object 가 null 이 아닌지 체크
* 4. void assertNull(Object object) // Object 가 null 인지 체크
* 5. void assertTrue(boolean condition) // true 인지 체크
* 6. void fail() // 무조건 fail
*
*/
public class TestJunit1 {
@Test
public void test() {
int num = 5;
String temp = null;
String str = "안녕하세요";
//assertEquals("안녕하세요1", str);
assertEquals("안녕하세요", str);
assertFalse(num > 6);
//assertFalse(num > 2);
//assertNotNull(temp);
assertNull(temp);
System.out.println(12.3 / 4.1);
// 실수는 오차가 발생할 수 있음
// double/float 실수 연산 값의 오차범위 delta 값
//assertEquals(3.0, 12.3 / 4.1); // FAIL
assertEquals(3.0, 12.3 / 4.1, 0.1); // pass
}
}
** [src/test/java] com.mvn.javaproj2 > TestJunit2.java
package com.mvn.javaproj2;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import junit.framework.TestCase;
public class TestJunit2 extends TestCase {
@Before
public void before() {
System.out.println("[before()]");
}
@After
public void after() {
System.out.println("[after()]");
}
@BeforeClass
public static void beforeClass() {
System.out.println("<<beforeClass()>>");
}
@AfterClass
public static void afterClass() {
System.out.println("<<afterClass()>>");
}
@Test
public void testA() {
System.out.println("testA()");
System.out.println("No. of Test Case = " + this.countTestCases());
System.out.println("Test Case Name = " + this.getName());
}
@Test
public void testB() {
System.out.println("testB()");
System.out.println("No. of Test Case = " + this.countTestCases());
setName("B테스트입니다.");
System.out.println("Test Case Name = " + this.getName());
}
@Test
public void testC() {
System.out.println("testC()");
System.out.println("No. of Test Case = " + this.countTestCases());
System.out.println("Test Case Name = " + this.getName());
}
@Test
public void testD() {
System.out.println("testD()");
System.out.println("No. of Test Case = " + this.countTestCases());
System.out.println("Test Case Name = " + this.getName());
}
}
** [src/test/java] com.mvn.javaproj2 > TestParameter.java
package com.mvn.javaproj2;
import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.Collection;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
/**
* JUnit 파라미터화 테스트(Parameterized Test)
*
* 동일한 테스트를 @Parameters 컬렉션의 원소 개수만큼 반복 실행
* Parameterized 클래스는 JUnit이 제공하는 많은 테스트 러너중 하나
*/
@RunWith(value = Parameterized.class)
public class TestParameter {
private int expected;
private int valueOne;
private int valueTwo;
@Parameters
public static Collection<Integer[]> getTestParameters() {
return Arrays.asList(new Integer[][] {
{2, 1, 1}, // expected, valueOne, valueTwo
{3, 2, 1},
{4, 3, 1},
{5, 2, 3}
//, {3, 1, 1}
});
}
public TestParameter(int expected, int valueOne, int valueTwo) {
super();
System.out.println("TestParameter() 생성");
this.expected = expected;
this.valueOne = valueOne;
this.valueTwo = valueTwo;
}
@Test
public void sum() {
Calculator cal = new Calculator();
assertEquals(expected, cal.add(valueOne, valueTwo));
System.out.println("테스트 통과: " + expected + ", " + valueOne + ", " + valueTwo);
}
// 생성자는 4번 생성되었지만, 놀랍게도 @BeforeClass는 1번만 출력된다!
@BeforeClass
public static void beforeClass() {
System.out.println("@BeforeClass");
}
}
'웹_프론트_백엔드 > JAVA프레임윅기반_풀스택' 카테고리의 다른 글
2020.07.08 (0) | 2020.07.08 |
---|---|
애플리케이션_테스트 시험(제출 코드와 풀이) (0) | 2020.07.07 |
2020.07.06 (0) | 2020.07.06 |
2020.07.06 (0) | 2020.07.06 |
2020.07.03 (0) | 2020.07.03 |