import javax.sql.DataSource;

import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

@Configuration
@PropertySource("classpath:/application.properties")
public class DatasourceConfiguration {
	@Autowired
	private ApplicationContext applicationContext;
	
	@Bean
	@ConfigurationProperties(prefix="spring.datasource.hikari")
	public HikariConfig hikariConfig() {
		return new HikariConfig();
	}
	
	@Bean
	public DataSource dataSource() throws Exception {
		DataSource dataSource = new HikariDataSource(hikariConfig());
		return dataSource;
	}
	
	@Bean
	public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
		SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
		sqlSessionFactoryBean.setDataSource(dataSource);
		
		sqlSessionFactoryBean.setConfigLocation(applicationContext.getResource("classpath:mybatis-config.xml"));
		sqlSessionFactoryBean.setMapperLocations(applicationContext.getResources("classpath:/mapper/**/*Mapper.xml"));
		return sqlSessionFactoryBean.getObject();
	}

	
	@Bean(name="batchSqlSessionTemplate") 
	public SqlSessionTemplate batchSqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { 
		 return new SqlSessionTemplate(sqlSessionFactory, ExecutorType.BATCH); 
	}
	
	@Bean(name="sqlSessionTemplate") 
	public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
		return new SqlSessionTemplate(sqlSessionFactory);
	}
	
	
	/**
	 * 트렌젝션 관리
	 * @param dataSource
	 * @return
	 */
	@Bean
	public PlatformTransactionManager transactionManager(DataSource dataSource) {
		return new DataSourceTransactionManager(dataSource);
	}
	

	
}

 

 

 

 

아래와같이 적용

	/**
	 * DB컨넥션 후 Connection객체를 반환한다.
	 * @return
	 * @throws SQLException
	 */
	private Connection getConnection() throws Exception{

		ApplicationContext ctx = ApplicationContextAwareExtends.getApplicationContext();
		DataSource dataSource =  ctx.getBean(DatasourceConfiguration.class).dataSource();
		
		return dataSource.getConnection();
	}

@Value 어노테이션으로 application.properties의 값을 가져올 수 있습니다. 

 

@Value 어노테이션은 Spring boot에서 제공하는 어노테이션입니다. 빈(bean)이 생성되는 시점에 

값을 할당하기 위해 사용됩니다. 

 

일반적으로 개발, 품질, 운영서버와 같이 환경 값이 변경되는 경우 application.properties에 설정된 값을 사용하기 위해 사용되기도 합니다. 

 

아래와 같이 application.properties에 값이 설정되어 있을 때

#EAI Call Url
eai.call.url=http://abc.abccdd.com/restapi/

 

@Value 어노테이션을 이용하여 갑을 주입하는 방법은 아래와 같습니다.

@Value("${eai.call.url}")
private String eaiUrl;

 

eaiUrl이라는 String 변수에 http://abc.abccdd.com/restapi/ 값이 담기게 됩니다. 

 

주의할 점은 변수 선언시 static으로 선언하면 값이 주입되지 않습니다. 

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

             <parent>

                           <groupId>org.springframework.boot</groupId>

                           <artifactId>spring-boot-starter-parent</artifactId>

                           <version>2.5.7</version>

                           <relativePath/>

             </parent>

             <groupId>ap-drwb</groupId>

             <artifactId>ap-drwb</artifactId>

             <version>1.0.0</version>

             <packaging>war</packaging>

             <name>drwb</name>

             <description>drwb</description>


 

             <properties>

                           <java.version>17</java.version>

                           <spring.version>5.3.13</spring.version>

                           <spring.boot.version>2.5.7</spring.boot.version>

                           <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

             </properties>


 

             <repositories>

                           <repository>

                                        <id>cenrtal</id>

                                        <url>https://repo1.maven.org/maven2/</url>

                           </repository>

                           <repository>

                                        <id>redhat-ga</id>

                                        <url>https://maven.repository.redhat.com/ga/</url>

                           </repository>

                           <repository>

                                        <id>mulesoft-ga</id>

                                        <url>https://repository.mulesoft.org/nexus/content/repositories/public/</url>

                           </repository>

                           <!--

                           <repository>

                                        <id>mergyaPub</id>

                                        <url>https://nexus.emergya.es/nexus/content/repositories/public/</url>

                           </repository>-->

             </repositories>


 

             <dependencies>

                           <!-- marked the embedded servlet container as provided --> 

                           <dependency>

                               <groupId>javax.servlet</groupId>

                               <artifactId>javax.servlet-api</artifactId>

                               <scope>provided</scope>

                           </dependency>

                           <dependency>

                               <groupId>org.bouncycastle</groupId>

                               <artifactId>bcmail-jdk14</artifactId>

                               <version>1.38</version>

                           </dependency>

                           <dependency>

                               <groupId>org.bouncycastle</groupId>

                               <artifactId>bcprov-jdk14</artifactId>

                               <version>1.38</version>

                           </dependency>

                           <dependency>

                               <groupId>org.bouncycastle</groupId>

                               <artifactId>bctsp-jdk14</artifactId>

                               <version>1.38</version>

                           </dependency>

                           <dependency>

                               <groupId>org.codehaus.castor</groupId>

                               <artifactId>castor</artifactId>

                               <version>1.2</version>

                           </dependency>

                           <dependency>

                               <groupId>commons-beanutils</groupId>

                               <artifactId>commons-beanutils</artifactId>

                               <version>1.8.3</version>

                           </dependency>

                           <dependency>

                               <groupId>commons-codec</groupId>

                               <artifactId>commons-codec</artifactId>

                           </dependency>

                           <dependency>

                               <groupId>commons-collections</groupId>

                               <artifactId>commons-collections</artifactId>

                               <version>3.2</version>

                           </dependency>

                           <dependency>

                               <groupId>commons-dbcp</groupId>

                               <artifactId>commons-dbcp</artifactId>

                               <version>1.4</version>

                           </dependency>

                           <dependency>

                               <groupId>commons-digester</groupId>

                               <artifactId>commons-digester</artifactId>

                               <version>2.1</version>

                           </dependency>

                           <dependency>

                               <groupId>commons-lang</groupId>

                               <artifactId>commons-lang</artifactId>

                               <version>2.4</version>

                           </dependency>

                           <dependency>

                               <groupId>commons-logging</groupId>

                               <artifactId>commons-logging</artifactId>

                               <version>1.1.1</version>

                           </dependency>

                           <dependency>

                               <groupId>dom4j</groupId>

                               <artifactId>dom4j</artifactId>

                               <version>1.6.1</version>

                           </dependency>

                           <dependency>

                               <groupId>org.eclipse.jdt</groupId>

                               <artifactId>ecj</artifactId>

                               <version>3.18.0</version>

                           </dependency>

                           <dependency>

                               <groupId>net.sf.ezmorph</groupId>

                               <artifactId>ezmorph</artifactId>

                               <version>1.0.4</version>

                           </dependency>

                           <dependency>

                               <groupId>com.zaxxer</groupId>

                               <artifactId>HikariCP</artifactId>

                           </dependency>

                           <dependency>

                               <groupId>com.fasterxml.jackson.core</groupId>

                               <artifactId>jackson-annotations</artifactId>

                           </dependency>

                           <dependency>

                               <groupId>com.fasterxml.jackson.core</groupId>

                               <artifactId>jackson-core</artifactId>

                           </dependency>

                           <dependency>

                               <groupId>com.fasterxml.jackson.core</groupId>

                               <artifactId>jackson-databind</artifactId>

                           </dependency>

                           <dependency>

                               <groupId>com.fasterxml.jackson.datatype</groupId>

                               <artifactId>jackson-datatype-jdk8</artifactId>

                           </dependency>

                           <dependency>

                               <groupId>com.fasterxml.jackson.datatype</groupId>

                               <artifactId>jackson-datatype-jsr310</artifactId>

                           </dependency>

                           <dependency>

                               <groupId>com.fasterxml.jackson.module</groupId>

                               <artifactId>jackson-module-parameter-names</artifactId>

                           </dependency>

                           <dependency>

                               <groupId>jakarta.annotation</groupId>

                               <artifactId>jakarta.annotation-api</artifactId>

                           </dependency>

                           <dependency>

                               <groupId>org.jasypt</groupId>

                               <artifactId>jasypt</artifactId>

                               <version>1.9.3</version>

                           </dependency>

                           <dependency>

                               <groupId>com.sun.mail</groupId>

                               <artifactId>javax.mail</artifactId>

                               <version>1.5.2</version>

                           </dependency>

                           <dependency>

                               <groupId>jfree</groupId>

                               <artifactId>jcommon</artifactId>

                               <version>1.0.15</version>

                           </dependency>

                           <dependency>

                               <groupId>eclipse</groupId>

                               <artifactId>jdtcore</artifactId>

                               <version>3.1.0</version>

                           </dependency>

                           <dependency>

                               <groupId>jfree</groupId>

                               <artifactId>jfreechart</artifactId>

                               <version>1.0.12</version>

                           </dependency>

                           <dependency>

                               <groupId>net.sf.json-lib</groupId>

                               <artifactId>json-lib-ext-spring</artifactId>

                               <version>1.0.2</version>

                           </dependency>

                           <dependency>

                               <groupId>org.slf4j</groupId>

                               <artifactId>jul-to-slf4j</artifactId>

                           </dependency>

                           <dependency>

                               <groupId>org.apache.logging.log4j</groupId>

                               <artifactId>log4j-api</artifactId>

                           </dependency>

                           <dependency>

                               <groupId>log4j</groupId>

                               <artifactId>log4j</artifactId>

                               <version>1.2.14</version>

                           </dependency>

                           <dependency>

                               <groupId>org.bgee.log4jdbc-log4j2</groupId>

                               <artifactId>log4jdbc-log4j2-jdbc4.1</artifactId>

                               <version>1.16</version>

                           </dependency>

                           <dependency>

                               <groupId>org.apache.logging.log4j</groupId>

                               <artifactId>log4j-to-slf4j</artifactId>

                           </dependency>

                           <dependency>

                               <groupId>ch.qos.logback</groupId>

                               <artifactId>logback-classic</artifactId>

                           </dependency>

                           <dependency>

                               <groupId>ch.qos.logback</groupId>

                               <artifactId>logback-core</artifactId>

                           </dependency>

                           <dependency>

                               <groupId>com.navercorp.lucy</groupId>

                               <artifactId>lucy-xss</artifactId>

                               <version>1.6.3</version>

                           </dependency>

                           <dependency>

                               <groupId>org.mybatis</groupId>

                               <artifactId>mybatis</artifactId>

                               <version>3.5.14</version>

                           </dependency>

                           <dependency>

                               <groupId>org.mybatis</groupId>

                               <artifactId>mybatis-spring</artifactId>

                               <version>3.0.3</version>

                           </dependency>

                           <dependency>

                               <groupId>org.mybatis.spring.boot</groupId>

                               <artifactId>mybatis-spring-boot-starter</artifactId>

                               <version>3.0.3</version>

                           </dependency>

                           <dependency>

                               <groupId>javax.servlet</groupId>

                               <artifactId>jstl</artifactId>

                           </dependency>

                           <dependency>

                               <groupId>javax.activation</groupId>

                               <artifactId>activation</artifactId>

                               <version>1.1.1</version>

                           </dependency>

                           <!-- OJDBC-->

                           <dependency>

                               <groupId>com.oracle.database.jdbc</groupId>

                               <artifactId>ojdbc11</artifactId>

                               <version>21.1.0.0</version>

                           </dependency>

                           <dependency>

                               <groupId>com.mchange</groupId>

                               <artifactId>mchange-commons-java</artifactId>

                               <version>0.2.15</version>

                           </dependency>

                           <dependency>

                               <groupId>org.apache.poi</groupId>

                               <artifactId>poi</artifactId>

                               <version>3.9</version>

                           </dependency>

                           <dependency>

                               <groupId>org.apache.poi</groupId>

                               <artifactId>poi-ooxml</artifactId>

                               <version>3.9</version>

                           </dependency>

                           <dependency>

                               <groupId>org.apache.poi</groupId>

                               <artifactId>poi-ooxml-schemas</artifactId>

                               <version>3.9</version>

                           </dependency>

                           <dependency>

                               <groupId>org.quartz-scheduler</groupId>

                               <artifactId>quartz</artifactId>

                               <version>2.3.2</version>

                           </dependency>

                           <dependency>

                               <groupId>org.yaml</groupId>

                               <artifactId>snakeyaml</artifactId>

                           </dependency>

                           <dependency>

                               <groupId>org.slf4j</groupId>

                               <artifactId>slf4j-api</artifactId>

                           </dependency><!--

                           <dependency>

                               <groupId>org.springframework.boot</groupId>

                               <artifactId>spring-boot</artifactId>

                               <version>${spring.boot.version}</version>

                           </dependency>

                           <dependency>

                               <groupId>org.springframework.boot</groupId>

                               <artifactId>spring-boot-autoconfigure</artifactId>

                               <version>${spring.boot.version}</version>

                           </dependency>-->

                 <dependency> 

                     <groupId>org.springframework.boot</groupId> 

                     <artifactId>spring-boot-starter-tomcat</artifactId>

                     <scope>provided</scope> 

                 </dependency>

                 <dependency>  

                                        <groupId>org.springframework.boot</groupId>  

                                        <artifactId>spring-boot-starter-web</artifactId>

                           </dependency>

                           <dependency>

                               <groupId>org.springframework</groupId>

                               <artifactId>spring-web</artifactId>

                           </dependency>

                           <dependency>

                               <groupId>org.springframework</groupId>

                               <artifactId>spring-jdbc</artifactId>

                           </dependency>

                           <dependency>

                               <groupId>org.springframework</groupId>

                               <artifactId>spring-context-support</artifactId>

                           </dependency>

                           <dependency>

                               <groupId>org.springframework</groupId>

                               <artifactId>spring-expression</artifactId>

                           </dependency>

                           <dependency>

                               <groupId>org.springframework</groupId>

                               <artifactId>spring-webmvc</artifactId>

                           </dependency>

                           <dependency>

                               <groupId>org.springframework.security</groupId>

                               <artifactId>spring-security-web</artifactId>

                           </dependency>

                           <dependency>

                               <groupId>org.springframework.security</groupId>

                               <artifactId>spring-security-config</artifactId>

                           </dependency>

                           <dependency>

                               <groupId>org.apache.tomcat.embed</groupId>

                               <artifactId>tomcat-embed-jasper</artifactId>

                           </dependency>

                           <dependency>

                               <groupId>com.lowagie</groupId>

                               <artifactId>itext</artifactId>

                         <version>2.1.7</version>

                         <scope>system</scope>

                               <systemPath>${basedir}/src/main/webapp/WEB-INF/lib/itext-2.1.7.jar</systemPath>

                           </dependency>

                           <dependency>

                               <groupId>net.sf.jasperreports</groupId>

                               <artifactId>jasperreports</artifactId>

                               <version>5.2.0</version>

                               <scope>system</scope>

                               <systemPath>${basedir}/src/main/webapp/WEB-INF/lib/jasperreports-5.2.0.jar</systemPath>

                           </dependency>

                           <dependency>

                               <groupId>commons-email</groupId>

                               <artifactId>commons-email</artifactId>

                               <version>1.4</version>

                               <scope>system</scope>

                               <systemPath>${basedir}/src/main/webapp/WEB-INF/lib/commons-email-1.4.jar</systemPath>

                           </dependency>

             </dependencies>


 

             <build>

                           <plugins>

                                        <plugin>

                                 <groupId>org.springframework.boot</groupId>

                                 <artifactId>spring-boot-maven-plugin</artifactId>

                               </plugin>

                           </plugins>

             </build>

</project>

Kotlin 프로그래밍 언어 알아보기 

기본문법에 대해서 모두 설명하기에는 양이 많아 링크로 대체하도록 하겠습니다. 

아래 사이트에서 기본적인 문법 및 잘못된 코드 스타일등을 확인 할 수 있으며 내용은 크게 무겁지 않으니 깊이 있는 내용을 원하시는 경우 별도의 다른 방법(검색이나 도서, 온라인 동영상강좌)등을 확인하시기 바랍니다. 

 https://developer.android.com/kotlin/learn?hl=ko

 

Kotlin 프로그래밍 언어 알아보기  |  Android 개발자  |  Android Developers

Kotlin 프로그래밍 언어 알아보기 Kotlin은 전 세계 Android 개발자가 널리 사용하는 프로그래밍 언어입니다. 이 주제는 활용도를 높이기 위한 Kotlin 단기 집중과정입니다. 변수 선언 Kotlin은 두 키워드

developer.android.com

 

Kotlin 개발을 위한 환경 설정

 

먼저  IntelliJ IDEA기반의 안드로이드 스튜디오를 다운받도록 합니다. 설치 파일의 용량은 800 ~ 900 MB이며 설치 과정중 추가 다운로드 단계가 있습니다.  

https://developer.android.com/studio?hl=ko

 

Download Android Studio and SDK tools  |  Android Developers

The official IDE for Android app developers.

developer.android.com

다운로드 버튼 클릭 후 약관 동의 단계가 나오며 동의하면 다운로드가 진행됩니다.

 

설치파일은 exe 형태로 Install 되어지며 일반적인 프로그램 설치와 유사하게 Next를 클릭하여 무난하게 설치 할 수 있습니다. 

  • 설치 중간에 컴포넌트 약관 동의가 나오는데 모두 Accept를 눌러 동의(컴포넌트 별로)해주셔야 합니다. 동의시 컴포넌트 다운로드를 실행합니다.
  •  기존에 설치했던 이력이 있는 사용자를 위해서 환경설정을 가져다 사용할 수 있는데 기존 사용자는 기존 설정파일 경로가 자동으로 찾아지면 사용하셔도 되며, 처음 사용자는 Do not import settings를 선택합니다.

 

  •  Install Type을 물어보는 경우 무난하게 Standard를 선택합니다.
  • 테마는 원하는 테마를 선택한 후 Next 버튼을 눌러 진행합니다.

 

모든 설치가 정상적으로 진행되었을 경우 아래와 같은 화면을 볼 수 있습니다.  여기까지 안드로이드 스튜디오 설치에 대한 부분은 진행이 다 되었다고 볼 수 있습니다. 

 

'Development > Android-Kotlin' 카테고리의 다른 글

Android-Kotlin 시작하기  (0) 2022.03.08

코틀린(Kotlin)이란?

 

코틀린은 ‘젯브레인스(JetBrains)’라는 회사에서 만든 안드로이드 개발을 위한 프로그래밍 언어로, 2016년도에 정식 발표되었습니다. 코틀린은 기존에 안드로이드 어플리케이션 개발에 활용되는 자바(Java) 언어를 보완하고 대체하기 위해 탄생했는데요. 때문에 기존에 자바 언어로 동작하던 환경에서 코틀린 언어도 100% 호환되는 것이 특징입니다. 이는 기존에 자바로 개발하던 프로그램은 모두 코틀린으로도 개발할 수 있다는 의미입니다.

 

2017년 열린 구글 I/O라는 컨퍼런스에서 코틀린은 공식 지원 언어로 채택되었습니다. 공식 지원 언어로 채택이 되었다는 건 과연 어떤 의미일까요? 구글이 코틀린을 공식 지원 언어로 채택하면서, 코틀린 플러그인을 안드로이드 스튜디오(Android Studio) 3.0에서 바로 다운로드하여 이용할 수 있게 되었다는 의미입니다. 이외에도 안드로이드 공식 문서의 예제 코드도 코틀린으로 제공되는 것을 확인할 수 있습니다.

 

Android 개발이 Kotlin 우선인 이유

Google은 컨퍼런스, 고객 자문위원회(CAB), Google 개발자 전문가(GDE) 및 자사 개발자 연구를 통해 개발자로부터 직접 받은 의견을 검토했습니다. 많은 개발자가 이미 Kotlin을 즐겨 사용하고 있으며 Kotlin 지원 추가에 관한 요청이 분명했습니다. 개발자가 말하는 Kotlin을 사용한 코드 작성의 이점은 다음과 같습니다.

  • 표현력이 높고 간결함: 적은 노력으로 많은 작업을 할 수 있습니다. 상용구 코드를 적게 사용하면서도 아이디어를 풍부하게 표현할 수 있습니다. Kotlin을 사용하는 전문 개발자 중 67%가 Kotlin을 통해 생산성이 높아졌다고 말합니다.
  • 더 안전한 코드: Kotlin에는 null 포인터 예외와 같은 일반적인 프로그래밍 실수를 방지하는 데 도움이 되는 여러 언어 기능이 있습니다. Kotlin 코드가 포함된 Android 앱은 다운될 가능성이 20% 낮습니다.
  • 호환성: Kotlin에서 자바 기반 코드를 호출하거나 자바 기반 코드에서 Kotlin을 호출합니다. Kotlin은 자바 프로그래밍 언어와 100% 호환되므로 프로젝트에서 Kotlin을 원하는 만큼 사용할 수 있습니다.
  • 구조화된 동시 실행: Kotlin 코루틴을 사용하면 비동기 코드를 차단 코드처럼 쉽게 사용할 수 있습니다. 코루틴은 네트워크 호출부터 로컬 데이터 액세스에 이르기까지 백그라운드 작업 관리를 크게 단순화합니다.

 

Kotlin 우선이란 무엇을 의미할까요?

Jetpack 라이브러리, 샘플, 문서, 교육 콘텐츠와 같은 새로운 Android 개발 도구와 콘텐츠를 빌드할 때 Google은 Kotline 사용자를 염두에 두고 디자인하는 동시에 자바 프로그래밍 언어에서 Google의 API를 사용할 수 있도록 지원을 계속 제공합니다.

  JAVA Kotlin
플랫폼 SDK 지원
Android 스튜디오 지원
린트
가이드 문서 지원
API 문서 지원
AndroidX 지원
AndroidX Kotlin 전용 API(KTX, 코루틴 등) 해당 사항 없음
온라인 교육 최상의 결과
샘플 최상의 결과
다중 플랫폼 프로젝트 아니요
Jetpack Compose 아니요
컴파일러 플러그인 지원 아니요 예: Kotlin Symbol Processing API는 Google에서 경량 컴파일러 플러그인을 개발하기 위해 만들었습니다.

 

다음에는 설치 과정을 설명하도록 하겠습니다.

'Development > Android-Kotlin' 카테고리의 다른 글

코틀린(Kotlin) 기본 문법 및 환경 설정  (0) 2022.03.08

Log4j 란?

Apache에서 만든 로깅용 자바기반의 오픈소스 라이브러리이다. 디버깅용이나 로그 적재에 주로사용한다.

Log for java라는 뜻을 줄여서 Log4j 라고 하며 Jakarta-project에서 Java를 위한 프로젝트 중 하나이다.

간단히 말해 로그를 출력하기 위한 라이브러리이다.

 

log4j 가 없어도 로그는 출력할 수 있지만 각 소스마다 sysout을 이용해 로그를 출력한다면 디버깅 로그가 필요 없을 경우에는 모두 추적하여 삭제하는 번거러움이 있고 sysout은 호출하면 할 수록 성능이 저하된다. 

(궁금한 경우 루프문을 작성하여 sysout을 계속 출력해 보면 알 수 있다.)

 


취약점

최근 log4j에 대한 취약점으로 큰 이슈가 발생하였다.  JNDI Injection 취약점을 이용하여 서버에서 악성 코드를 실행할 수 있다.  아래와 같은 위험이 있다고 한다.

  • 대상 컴퓨터(서버)의 모든 권한 취득 가능
  • 비밀번호 없이 내부망 접근 가능
  • 악성 프로그램(랜섬웨어 등) 실행 가능
  • 기업의 중요한 자료 삭제 등

 


취약점 조치

버전 업그레이드를 위해 공홈에서 사용중인 JDK 버전에 맞는 라이브러리를 다운로드 받는다. 

https://logging.apache.org/log4j/2.x/download.html#

 

Log4j – Download Apache Log4j 2

<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apa

logging.apache.org

파일을 다운로드 받은 후 압축파일의 내용을 보면 필요한 파일보다 더 많은 파일이 있다. 

지금 우리가 수행할 작업은 1.x 버전에서 2.x 버전으로 변경하는 작업이므로 해당 작업을 중점으로 설명하겠다. 

( log4j2-2.x.x 버전 업그레이드는 라이브러리만 교체하면 되는것으로 알고 있음)

 

 

 

<라이브러리 교체>

프로젝트의 상황에 따라 일부 라이브러리는 차이가 있을 수 있다. 

(예를 들면 remix / jdbc가 붙은 log4j 관련 라이브러리)

그러나 버전 업그레이드에 반드시 필요한 파일은 3개가 있으며 slf4j를 사용하는 경우 1개의 교체해야하는 파일이 있다.

log4j-core-2.x.x.jar log4j-api-2.x.x.jar log4j-web-2.x.x.jar log4j-slf4j-impl-2.x.x.jar
추가 Slf4j 사용시 추가
( 교체 : slf4j-log4j12-1.x.x.jar)

 

기존 프로젝트에 삭제되어야하는 라이브러리는 다음과 같다.

  • log4j-1.x.x.jar
  • slf4j-log4j12-1.x.x.jar  (slf4j를 사용하지 않는 경우에는 해당 파일이 없을 수 있으나 대부분의 프로젝트에는 있다.)

추가되어야 하는 라이브러리 

  • log4j-core-2.x.x.jar
  • log4j-api-2.x.x.jar
  • log4j-web-2.x.x.jar
  • log4j-slf4j-impl-2.x.x.jar  / log4j2-2.x.x용 바인딩 파일 (slf4j를 사용하지 않는 경우 제외)

slf4j를 사용하며 기존에 존재하는 라이브러리 중 유지해야하는 라이브러리

  • slf4j-api-1.x.x.jar    /  기존 소스에서 API를 사용하고 있으므로 삭제하지 않음

 

 

<설정 변경 : WEB.XML>

log4j2.xml 경로설정 - log4j-2.x 버전에서는 web.xml에서 경로나 파일명을 명시하지 않으면 기본값으로 classpath: 경로에서 log4j2-test.xml 또는 log4j2.xml 파일을 찾는다고 한다. (log4j 에서도 동일했던 것 같은데..) 

하지만 명확하게 하기 위해 별도의 설정을 하도록한다.

<!-- 대상파일 web.xml -->

<!-- AS-IS  : 변경 전-->
<context-param>
	<param-name>log4jConfigLocation</param-name>
    <param-value>classpath:/log4j.xml</param-value>
</context-param>

<listener>
	<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

<!-- To-be : 변경 후-->
<context-param>
	<param-name>log4jConfiguration</param-name>
    <param-value>classpath:/log4j2.xml</param-value>
</context-param>
<listener>
	<listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
</listener>

web.xml에 해당 코드가 없는경우 추가하도록 한다.

경험으로는 spring 3.1 버전에서는 해당 코드가 없는 프로젝트가 있었으며 spring 3.2 이후부터는 해당 코드가 있었다.

 

 

 

<설정 변경 : LOG4J2.XML>

log4j2.xml 파일에 대한 작성법은 여기서 다루지 않도록 한다.
     관련링크 :   https://logging.apache.org/log4j/2.x/manual/configuration.html

 

Log4j – Configuring Log4j 2

Configuration Inserting log requests into the application code requires a fair amount of planning and effort. Observation shows that approximately 4 percent of code is dedicated to logging. Consequently, even moderately sized applications will have thousan

logging.apache.org

 

사용중인 설정파일의 내용은 아래와 같다. 

<!-- 신규작성 파일 : log4j2.xml -->
<?xml version="1.0" encoding="UTF-8"?>

<Configuration status="DEBUG">
	<Properties>
		<Property name="logNm">log_pattern_Layout</Property>
		<Property name="layoutPattern">[%d{ISO8601}][%5p] [%c{4}]: %m%n</Property>
	</Properties>
			
	<Appenders>
		<Console name="console" target="SYSTEM_OUT">
		    <PatternLayout pattern="${layoutPattern}" />
		</Console>
		<RollingRandomAccessFile
			name="rolling_log"
			fileName="./logs/file.log"
			filePattern="./logs/pjt/pjt-%d{yyyy-MM-dd_HH}_%i.log"
			immediateFlush="false"
			append="true"
			ignoreExceptions="false">
			<PatternLayout pattern="${layoutPattern}" />
			<Policies>
				<!-- 30MB 용량이 초과시 DefaultRolloverStrategy 정책만큼 넘버링 -->
				<SizeBasedTriggeringPolicy size="30 MB" />
				<!-- 일별 로그 파일 생성-->
				<TimeBasedTriggeringPolicy interval="1" modulate="true" />
			</Policies>
			<!-- 롤링 파일 1000개 까지 생성 -->
			<DefaultRolloverStrategy max="1000" />
		</RollingRandomAccessFile>
		
		<Async name="async_log" includeLocation="true">
			<AppenderRef ref="rolling_log" />
		</Async>

		
	</Appenders>

	

	<Loggers>
		<!-- 스프링 프레임워크에서 찍는건 level을 info로 설정 -->
		<logger name="org.springframework" level="info" additivity="false" >
			<AppenderRef ref="console" />
			<AppenderRef ref="async_log" />
		</logger>
		<Logger name="jdbc.connection" level="info" additivity="false">
			<AppenderRef ref="async_log" />
		</Logger>
		<Logger name="jdbc.audit" level="error" additivity="false">
			<AppenderRef ref="async_log" />
		</Logger>
		<Logger name="jdbc.resultset" level="error" additivity="false">
			<AppenderRef ref="async_log" />
		</Logger>
		<Logger name="jdbc.resultsettable" level="error" additivity="false">
			<AppenderRef ref="async_log" />
		</Logger>
		
		<Logger name="jdbc.sqltiming" level="error" additivity="false">
			<AppenderRef ref="async_log" />
		</Logger>
		<Logger name="com.ibatis" level="error" additivity="false">
			<AppenderRef ref="async_log" />
		</Logger>
		<Logger name="java.sql" level="error" additivity="false">
			<AppenderRef ref="async_log" />
		</Logger>
		<Logger name="com.kpmg.kr" level="error" additivity="false">
			<AppenderRef ref="async_log" />
		</Logger>
		

		<Root level="debug">
			<AppenderRef ref="async_log" />
			<AppenderRef ref="console" />
		</Root>
	</Loggers>

</Configuration>

 

 

<설정 변경 : JAVA CODE내 사용>

slf4j를 사용했다면 과거 1.X 버전을 사용할때랑 동일하므로 변경할 내용이 없으나. 사용하지 않는 다면 아래 예제를 참조하여 수정하도록 한다.( 보통은 slf4j를 상당수 사용하기 때문에 ....)

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;

// logger name이 현재 클래스 경로인 것을 찾는다. 
private static Logger logger = LogManager.getLogger(this.getClass()); 

prvate static void write(String s){
	logger.info(s);
}

 

작업을 완료하고 콘솔(예를 들면 이클립스)에서 Was 기동시 붉은색 로그가 아닌 검정색 로그가 주르륵 올라간다면 적용이 완료되었다고 볼 수 있다. 

설정오류(설정에 오류는 있으나 컴파일 오류가 안나는 상태)의 경우 Was 기동시 붉은색 로그만 나타나게 된다면

즉, 스프링 관련 로그같은 별도의 검정색 텍스트가 보이지 않는다면 설정이 잘못되었다고 볼 수 있다. 

 

<오류 발생 Case>

모두 적용을 완료한 후 톰켓 기준 WAS 기동시 에러메세지가 나타나는 경우가 있다. 

 org.apache.tomcat.util.bcel.classfile.ClassFormatException: Invalid byte tag in constant pool: 19

해당 현상은 톰켓 버그로 이 문제가 해결된 버전은 Tomcat을 사용함으로써 해결이 가능하다.

  • Tomcat 9.0.x : 9.0.0.M18 이후
  • Tomcat 8.5.x : 8.5.12 이상 
  • Tomcat 8.0.x : 8.0.42 이상
  • Tomcat 7.0.x : 7.0.76 이상

해당내용 관련 StackOverflow

https://stackoverflow.com/questions/23541532/org-apache-tomcat-util-bcel-classfile-classformatexception-invalid-byte-tag-in

 

org.apache.tomcat.util.bcel.classfile.ClassFormatException: Invalid byte tag in constant pool: 15

I'm porting a webapp from Tomcat 7 to another server with Tomcat 7 but with Java 8. Tomcat starts successfully but in log catalina.out I get: org.apache.tomcat.util.bcel.classfile.ClassFormatExce...

stackoverflow.com

 

개요

Logback에서 발생하는 원격코드 실행 취약점 (CVE-2021-42550)[2]
-   공격자가 Logback구성파일인 logback.xml을 조작할 경우, 해당파일을 참조하는 과정에서 삽입된 JNDI*쿼리문을 실행 해 임의의 원격코드를 실행할 수 있는 취약점
※ 공격 전제조건
- Logback구성파일 logback.xml에 대한 쓰기 권한이나 해당파일을 수정/덮어쓰기 가능할 경우
- 수정된 구성파일 logback.xml을 환경에 적용(reload)할 수 있는 권한
 
* JNDI : 디렉토리 서비스에서 제공하는 데이터 및 객체를 발견하고 참고하기 위한 Java API
(Java Naming and Directory Interface의 약어)

 

영향받는버전

- 1.2.8 이하 모든버전
- 1.3.0-alpha10 이하 모든버전

 

해결방안

취약점 업데이트 (패치 적용 前 업무시스템의 서비스 영향 검토 후 적용할 것)
-   1.2.8이하 버전의 경우, 최신 버전(1.2.9) 업그레이드 적용 [3]
-   1.3.0-alpha10이하 버전의 경우, 1.3.0-alpha11로 업그레이드 적용[3]
※   1.3.x시리즈의 경우, 기본적으로 JAVA9 모듈화 되어 있으며 slf4j-api 버전 2.0.x 필요
(runtime에는 Java8이상이면 되지만, 소스에서 Logback을 빌드하려면 Java9 필요)

 

임시 조치방안 (패치 즉시적용 불가할 경우)

1)    구성파일 logback.xml파일의 권한을 read-only로 변경
※ logback.xml 파일 위치 : /src/main/resources/

 

 

참고사이트

[1]    https://nvd.nist.gov/vuln/detail/CVE-2021-42550
[2]    http://logback.qos.ch/news.html
[3]    https://repo1.maven.org/maven2/ch/qos/logback/

log4j는 현재 2.16까지 나온걸로 되어 있다.

이번에 난리난 취약점 때문에 일부 회사에서는 1.x 버전대를 사용하고 있어도 

1.x 버전은 2015년 EOS(기술지원종료) 되었기 때문에 최신버전으로 업데이트 하라는 조치사항이 나오기도 하여 

 

2.16버전이 아닌 2.15버전에 대한 URL을 찾아보았다.

 

https://downloads.apache.org/logging/log4j/2.15.0/

 

Index of /logging/log4j/2.15.0

 

downloads.apache.org

 

 

Quartz Scheduler를 사용하면 console log에 아래와 같은 로그가 주기적으로 나타나는 경우가 있다.

[org.quartz.core.QuartzSchedulerThread] batch acquisition of 0 triggers

이 로그가 보기 싫은 경우 logger를 설정하여 해결 할 수 있다.

 

  • org.quartz.core.QuartzSchedulerThread 클래스에 대한 로거를 작성 후 레벨을 error로 설정합니다.
  • root의 priority를 value를 debug로 설정합니다.
	<root>
		<priority value="debug" />   <-- 출력 로그 레벨 설정
        ....
        ...
        ..
		<appender-ref ref="console" />
	</root>

 

Log4j 2 XML Configuration

Xml 파일 위치

XML 파일 (log4j2.xml)을 작성하고, WEB-INF/classes 하위에 포함될 수 있도록 위치시킨다.
Log4j 2가 초기화될 때 자동으로 위 설정 파일을 읽어들인다

 

Xml 파일 정의 Sample

파일 (log4j.xml)을 작성 시 Log4j 2에서는 최상의 요소가 <Configuration>으로 변경 되었음을 기억해야 합니다.

<Configuration>요소 아래에 Logger, Appender, Layout 설정 등과 관련한 하위 요소를 정의

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

	<appender name="console" class="org.apache.log4j.ConsoleAppender">
		<param name="Target" value="System.out" />
		<layout class="org.apache.log4j.PatternLayout">
			<param name="ConversionPattern" value="[%-5p: %d] %m [%c]%n" />
		</layout>
	</appender>

	<logger name="jdbc.audit" additivity="false">
		<level value="warn" />
		<appender-ref ref="console" />
	</logger>
	<logger name="jdbc.resultset" additivity="false">
		<level value="warn" />
		<appender-ref ref="console" />
	</logger>
	<logger name="jdbc.resultsettable" additivity="false">
		<level value="info" />
		<appender-ref ref="console" />
	</logger>
	...
    
	<root>
		<priority value="debug" />
		<appender-ref ref="console" />
	</root>
</log4j:configuration>

관련/참고 사이트

http://logging.apache.org/log4j/2.x/manual/configuration.html

 

Log4j – Configuring Log4j 2

Configuration Inserting log requests into the application code requires a fair amount of planning and effort. Observation shows that approximately 4 percent of code is dedicated to logging. Consequently, even moderately sized applications will have thousan

logging.apache.org

http://logging.apache.org/log4j/2.x/manual/configuration.html#XML

 

Log4j – Configuring Log4j 2

Configuration Inserting log requests into the application code requires a fair amount of planning and effort. Observation shows that approximately 4 percent of code is dedicated to logging. Consequently, even moderately sized applications will have thousan

logging.apache.org

 

Logger의 사용

public class SampleClass extends HandlerInterceptorAdapter {

    protected Logger logger = LoggerFactory.getLogger(SampleClass.class);
    public String sampleMethod(Object obj) throws Exception {
    	logger.debug("logger 내용");
    }

    	

log Level

Log Level에 따라 log의 출력여부를 지정할 수 있다.

Log Level DESC
FATAL 아주 심각한 에러가 발생한 상태를 나타냄. 시스템적으로 심각한 문제가 발생해서 어플리케이션 작동이 불가능할 경우가 해당하는데, 일반적으로는 어플리케이션에서는 사용할 일이 없음.
ERROR 요청을 처리하는중 문제가 발생한 상태를 나타냄.
WARN 처리 가능한 문제이지만, 향후 시스템 에러의 원인이 될 수 있는 경고성 메시지를 나타냄.
INFO 로그인, 상태변경과 같은 정보성 메시지를 나타냄.
DEBUG 개발시 디버그 용도로 사용한 메시지를 나타냄.
TRACE 디버그 레벨이 너무 광범위한 것을 해결하기 위해서 좀더 상세한 상태를 나타냄.

 

Appender 설정

ConsoleAppender : 이클립스 console 같은곳에 로그를 출력하기 위해 사용합니다.

 <Console name="console" target="SYSTEM_OUT">
  <PatternLayout pattern="%d %5p [%c] %m%n" />
 </Console>

FileAppender ; 로그를 파일에 저장할 때 사용합니다.

<File name="file" fileName="./log file path/sample.log" append="false">
  <PatternLayout pattern="%d %5p [%c] %m%n" />
</File>	

 

log를 File과 Console에 동시에 쌓는 코드

<root>
	<priority value="debug" />
	<appender-ref ref="console" />
</root>

+ Recent posts