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

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>

먼저 답을 말하자면 별도 설치할 필요는 없습니다.

정확히는 해당 드라이버 jar 파일만 있으면 별도로 설치 할 필요는 없습니다.

 

DBMS 접속 시 사용되는 방식은 Thin 방식과 OCI 방식이 존재합니다. 

 

 

THIN 방식이라고 말하면 생소할 수 있는데 아래 예시처럼 Java 개발시 사용되는 문법의 경우 해당됩니다.

 

String driver = "oracle.jdbc.driver.OracleDriver";
String url = "jdbc:oracle:thin:@111.111.111.1:1521:dbsid";
.....
...
.

 

THIN방식은 순수하게 자바 패키지(클래스들)만으로 바로 DB와 연결하므로 범용성이 높습니다.

( OCI 방식은 플렛폼에 영향을 많이 받는데 비해.. )

상대적으로 OCI보다 속도가 느리긴 하지만 크게 느껴지는 정도는 아닙니다.(수행되는 작업에 따라 다를 수 있음)

 

 

다만 오라클클라이언트를 설치하게 되면 SQL*PLUS 같은 프로그램이 설치되기 때문에 필요할 수 있습니다. 

 

하지만 별도로 DB 접속을 하게되는 토트, 오렌지 등에서는 Oracle Clinet 설치가 필요합니다.

 

 

 

1. 개요

- iReport란?

iReportJasperReports 라이브러리를 통해 모든 종류의 Java 응용에 사용할 수 있고, 복잡한 보고서를 생성하는 오픈 소스 프로그램이다. 이 iReport는 100% Java로 구현됐으며, GNU (General Public License)에서 소스 코드를 배포한다.

 

iReport는 그래픽 인터페이스를 통해 어떤 종류의 복잡한 보고서도 간단하고 빠르게 생성할 수 있고, JasperReportsXML 문법을 공들여 배우지 않아도 개발 시간을 단축해 개발자에게 큰 도움을 준다.

 

즉,  iReportJasperReports를 위한 Reports Design Tool이라고 할 수 있다.

 

다운로드 서비스는 아래 사이트에서 이용할 수 있다.(무료

https://sourceforge.net/projects/ireport/

 

iReport-Designer for JasperReports

Download iReport-Designer for JasperReports for free. NOTE: iReport/Jaspersoft Studio Support Announcement: As of version 5.5.0, Jaspersoft Studio will be the official design client for JasperReports. iReport will remain as a supported product in maintenan

sourceforge.net

 

2. iReport 설치 및 실행

    a. 다운로드한 파일을 압축을 해제 

    b. 압축을 해제 한 디렉터리 하위의 bin 폴더의 ireport.exe 파일을 실행

 

 

3. iReport UI 설명

[iReport UI Layout

4. iReport 환경설정

    4-1. Class path 설정

        Tools의 Options window를 오픈하여 아래 그림과 같이 설정합니다. 

    

    4-2. Compile 경로 설정

        iReport는 컴파일된 .jasper 파일을 사용하여 서비스가 제공됩니다. 따라서 Complie path를 설정하여 서비스되는

        시스템에 자동으로 저장될 수 있도록 설정하는 편이 업무에 도움이 됩니다.

컴파일 된 jasper파일 경로 설정

    4-3. Database 연동

        iReport는 DB와 직접 통신하여 데이터를 질의하고 출력 할 수 있습니다. 해당 기능을 사용하기 위해서 먼저 JDBC

        연결 설정을 수행합니다.

 

이상으로 iReport 설정 방법을 알아보았습니다. 

 

Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener

 

 

톰켓 실행할때 해당 오류를 만날 수 있습니다. 

 

이유는 간단합니다. 라이브러리에 runtime 라이브러리가 추가되지 않아서 발생한 Exception 입니다.

 

 

 

 

 

 

 

일반적으로 이미지 타입이 RGB가 아닌 CMYK인 경우 


ImageIO.read() 를 이용하여 읽을 경우  Unsupported Image Type 가 발생한다.


일반적으로 CMYK타입 이미지는  ImageIO 로 read 하기 불가능하다




ImageIO.read(file); 를 이용해서 Exception이 발생할 경우 컨버터를 이용하여 처리하는 방식을 이용하여 오류를 줄일 수 있다. 



converter_Lib.zip



converter_Lib.zip의 icc 파일은 Cmyk2RgbConverter와 동일한 경로에 위치하면 된다. 



< Cmyk2RgbConverter.java >


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
public class Cmyk2RgbConverter {
 
    public static final int TYPE_RGB = 1;
    public static final int TYPE_CMYK = 2;
    public static final int TYPE_YCCK = 3;
 
    private static int colorTp = TYPE_RGB;
    private static boolean markerFlag = false;
 
 
 
    public static BufferedImage readImage(File file) throws IOException, ImageReadException {
        colorTp = TYPE_RGB;
        markerFlag = false;
 
        ImageInputStream stream = ImageIO.createImageInputStream(file);
        Iterator < itor_imgReader > iter = ImageIO.getitor_imgReaders(stream);
        while (iter.hasNext()) {
            itor_imgReader reader = iter.next();
            reader.setInput(stream);
 
            BufferedImage image;
 
            ICC_pf pf = null;
            try {
                image = reader.read(0);
                
                reader.reset();
            } catch (IIOException e) {
                colorTp = TYPE_CMYK;
                checkMarker(file);
                pf = Sanselan.getICCpf(file);
                Writablewr wr = (Writablewr) reader.readwr(0null);
 
                
                reader.reset();
 
                if (colorTp == TYPE_YCCK) {
                    convertYcck2Cmyk(wr);
                }
 
                if (markerFlag) {
                    convInvColors(wr);
                }
                image = convertCmykToRgb(wr, pf);
                image.flush();
            } finally {
                stream.close(); 
            }
 
            return image;
        }
 
        return null;
    }
 
    public static void checkMarker(File file) throws IOException, ImageReadException {
        JpegImageParser parser = new JpegImageParser();
        ByteSource byteSource = new ByteSourceFile(file);
        @SuppressWarnings("rawtypes")
        ArrayList segments = parser.readSegments(byteSource, new int[] {
            0xffee
        }, true);
        if (segments != null && segments.size() >= 1) {
            UnknownSegment app14Segment = (UnknownSegment) segments.get(0);
            byte[] data = app14Segment.bytes;
            if (data.length >= 12 && data[0== 'A' && data[1== 'd' && data[2== 'o' && data[3== 'b' && data[4== 'e') {
                markerFlag = true;
                int transform = app14Segment.bytes[11& 0xff;
                if (transform == 2)
                    colorTp = TYPE_YCCK;
            }
        }
    }
 
    public static void convertYcck2Cmyk(Writablewr wr) {
        int height = wr.getHeight();
        int width = wr.getWidth();
        int stride = width * 4;
        int[] rowData = new int[stride];
        for (int h = 0; h < height; h++) {
            wr.getPixels(0, h, width, 1, rowData);
 
            for (int x = 0; x < stride; x += 4) {
                int y = rowData[x];
                int cb = rowData[x + 1];
                int cr = rowData[x + 2];
 
                int c = (int)(y + 1.402 * cr - 178.956);
                int m = (int)(y - 0.34414 * cb - 0.71414 * cr + 135.95984);
                y = (int)(y + 1.772 * cb - 226.316);
 
                if (c < 0)
                    c = 0;
                else if (c > 255)
                    c = 255;
                if (m < 0)
                    m = 0;
                else if (m > 255)
                    m = 255;
                if (y < 0)
                    y = 0;
                else if (y > 255)
                    y = 255;
 
                rowData[x] = 255 - c;
                rowData[x + 1= 255 - m;
                rowData[x + 2= 255 - y;
            }
 
            wr.setPixels(0, h, width, 1, rowData);
        }
    }
 
    public static void convInvColors(Writablewr wr) {
        int height = wr.getHeight();
        int width = wr.getWidth();
        int stride = width * 4;
        int[] rowData = new int[stride];
        for (int h = 0; h < height; h++) {
            wr.getPixels(0, h, width, 1, rowData);
            for (int x = 0; x < stride; x++)
                rowData[x] = 255 - rowData[x];
            wr.setPixels(0, h, width, 1, rowData);
        }
    }
 
    public static BufferedImage convertCmykToRgb(wr cmykwr, ICC_pf cmykpf) throws IOException {
 
        if (cmykpf == null) {
            cmykpf = ICC_pf.getInstance(CMYKConverter.class.getResourceAsStream("ISOcoated_v2_300_eci.icc"));
        }
 
        ICC_ColorSpace cmykCS = new ICC_ColorSpace(cmykpf);
        BufferedImage rgbImage = new BufferedImage(cmykwr.getWidth(), cmykwr.getHeight(), BufferedImage.TYPE_INT_RGB);
        Writablewr rgbwr = rgbImage.getwr();
        ColorSpace rgbCS = rgbImage.getColorModel().getColorSpace();
        ColorConvertOp cmykToRgb = new ColorConvertOp(cmykCS, rgbCS, null);
        cmykToRgb.filter(cmykwr, rgbwr);
        return rgbImage;
    }
 
    public static void intToBigEndian(int value, byte[] array, int index) {
        array[index] = (byte)(value >> 24);
        array[index + 1= (byte)(value >> 16);
        array[index + 2= (byte)(value >> 8);
        array[index + 3= (byte)(value);
    }
 
}
 
cs


+ Recent posts