레이블이 Java인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Java인 게시물을 표시합니다. 모든 게시물 표시

2020년 3월 12일 목요일

[Spring] Jasypt를 이용하여 Property 암호화 하기 + 메이븐 플러그인


Spring 프로젝트의 Properties 파일에는 DB 연결정보, 이메일 계정, API Key 등의 보안에 민감한 정보들이 포함될 수 있습니다.
이 상태에서 프로젝트를 그대로 공유하게 되면 보안에 심각한 문제가 생길 수 있습니다.
이를 방지하기 위해 Spring 프로젝트에서 jasypt-spring-boot의 비밀번호 기반 암호화를 이용하여 중요한 정보들을 암호화하는 방법을 설명합니다.




참고
https://github.com/ulisesbocchio/jasypt-spring-boot




Dependency 추가





프로젝트의 pom.xml에 다음 Dependency를 추가합니다.




<dependency>
 <groupId>com.github.ulisesbocchio</groupId>
 <artifactId>jasypt-spring-boot-starter</artifactId>
 <version>3.0.2</version>
</dependency>




Property 설정





적용 및 테스트를 위해 application.properties에 다음과 같이 비밀번호를 작성합니다.
(실사용 시에는 비밀번호를 프로퍼티에서 삭제해주세요)




jasypt.encryptor.password=ExamplePassword123




-주의-
위처럼 비밀번호를 프로퍼티에 작성할 경우 결과적으로 비밀번호가 노출되기 때문에 보안 효과가 없습니다.
테스트 외에 실제 서비스에서 사용한다면 꼭 프로퍼티 파일 내 비밀번호를 삭제하고
비밀번호를 시스템 변수나 환경 변수에 등록하여 사용하시기를 권장합니다.




필수 프로퍼티는 jasypt.encryptor.password 밖에 없으며
이 외에 추가할 수 있는 프로퍼티는 다음과 같습니다.
작성하지 않으면 아래의 기본값이 적용됩니다.
자세한 내용은 https://github.com/ulisesbocchio/jasypt-spring-boot에서 확인해주세요.




jasypt.encryptor.algorithm=PBEWITHHMACSHA512ANDAES_256
jasypt.encryptor.key-obtention-iterations=1000
jasypt.encryptor.pool-size=1
jasypt.encryptor.provider-name=SunJCE
jasypt.encryptor.provider-class-name=null
jasypt.encryptor.salt-generator-classname=org.jasypt.salt.RandomSaltGenerator
jasypt.encryptor.iv-generator-classname=org.jasypt.iv.RandomIvGenerator
jasypt.encryptor.string-output-type=base64
jasypt.encryptor.proxy-property-sources=false
jasypt.encryptor.skip-property-sources=empty list




사용하기





테스트 작성





테스트 유닛을 작성하여 암복호화가 작동하는지 확인해봅니다.




@SpringBootTest
public class JasyptTests {

 @Autowired
 StringEncryptor configurationEncryptor;
 
 static final String TEST_PASSWORD = "테스트용 비밀번호 입니다.";
 
 @Test
 public void encryptTest() {
  String encryptedPassword = configurationEncryptor.encrypt(TEST_PASSWORD);
  System.out.println("encrypted password is : " + encryptedPassword);
  String decryptedPassword = configurationEncryptor.decrypt(encryptedPassword);
  assertThat(decryptedPassword).isEqualTo(TEST_PASSWORD);
 }
}




테스트가 성공하면 콘솔에서 아래와 비슷한 암호화된 문자열을 확인할 수 있습니다.




encrypted password is : cA8DhDVl27MeHDSQRn8GSfUFGn+Qif2n9Zv8OLlq67yiijVJTe0wqwzRE9eIBSlfNQ5HeYirCXMZFwXPbO7LAHe+q/PeWxNcYE9Tr1LeBEs=




프로퍼티에 적용





공개되면 안 되는 프로퍼티 값을 암호화한 후 아래와같이 ENC()로 감싸서 작성하게 되면 프로퍼티를 불러올 때 자동으로 복호화하여 적용합니다.




test=ENC(cA8DhDVl27MeHDSQRn8GSfUFGn+Qif2n9Zv8OLlq67yiijVJTe0wqwzRE9eIBSlfNQ5HeYirCXMZFwXPbO7LAHe+q/PeWxNcYE9Tr1LeBEs=)




여기까지 적용하게 되면 프로퍼티 파일 노출로 인한 정보 노출을 방지할 수 있습니다.




프로퍼티를 불러올 때 정상적으로 복호화가 되는지 테스트를 위해
위의 JasyptTests 클래스에 다음과 같이 테스트코드를 추가하였습니다.




@SpringBootTest
public class JasyptTests {
 // 기존 코드 생략
 ...

 @Value("${test}")
 String test;

 @Test
 public void propertyTest() {
  System.out.println("test password is : " + test);
  assertThat(test).isEqualTo(TEST_PASSWORD);
 }
}




테스트 정상적으로 완료되었다면 콘솔에서 복호화된 문자열을 확인할 수 있습니다.




test password is : 테스트용 비밀번호 입니다.




플러그인





위의 방식으로 민감한 정보들은 전부 암호화하여 사용하는 걸로도 충분하지만
플러그인과 메이븐 명령어를 이용하여 간단하게 암호화하는 방법을 소개합니다.




이를 위해서는 메이븐 명령어를 사용 가능해야 하며 메이븐 명령어의 기본적인 사용 방법은 다른 가이드를 참고해 주시길 바랍니다.




플러그인 추가





우선 플러그인 사용을 위해 pom.xml에 플러그인을 추가합니다.




<plugin>
 <groupId>com.github.ulisesbocchio</groupId>
 <artifactId>jasypt-maven-plugin</artifactId>
 <version>3.0.2</version>
</plugin>




프로퍼티 작성





프로퍼티를 작성할 때 암호화되지 않은 정보들을 DEC()로 감싸서 작성하게 되면 플러그인을 이용하여 일괄적으로 암호화 할 수 있습니다.




test=DEC(암호화되지 않은 테스트 프로퍼티 입니다.)




명령어를 이용하여 암복호화





콘솔에서 아래의 명령어로 application.properties 파일 내 DEC()로 감싸진 정보들을 일괄적으로 암호화 할 수 있습니다.
환경변수에 jasypt.encryptor.password를 등록해 놨다면 아래의 명령어에서 생략 가능합니다.




mvn jasypt:encrypt -Djasypt.encryptor.password="ExamplePassword123"




역으로 복호화도 가능합니다.




mvn jasypt:decrypt -Djasypt.encryptor.password="ExamplePassword123"




이를 이용하면 암호화된 정보를 좀 더 쉽게 수정하고 다시 암호화가 가능합니다.




프로퍼티 파일 지정하기





위처럼 명령어를 이용하면 application.properties가 아닌 application-test.properties 같은 파일은 암복호화가 되지 않습니다.
다른 파일을 암복호화 하고 싶을 경우 jasypt.plugin.path 파라미터로 파일을 지정할 수 있습니다.




mvn encrypt:encrypt -Djasypt.encryptor.password="ExamplePassword123" -Djasypt.plugin.path="file:src/main/test/application-dev.properties"




단독 값 암복호화 하기





아래의 명령어로 프로퍼티 파일과 별개로 단독 문자열을 암호화하거나 복호화가 가능합니다.




mvn jasypt:encrypt-value -Djasypt.encryptor.password="ExamplePassword123" -Djasypt.plugin.value="theValueYouWantToEncrypt"

mvn jasypt:decrypt-value -Djasypt.encryptor.password="ExamplePassword123" -Djasypt.plugin.value="DbG1GppXOsFa2G69PnmADvQFI3esceEhJYbaEIKCcEO5C85JEqGAhfcjFMGnoRFf"





[Spring Security] PasswordEncoder를 Bean에 등록하여 사용하기 -PasswordEncoderFactories로 DelegatingPasswordEncoder 생성하기


현재 진행 중인 프로젝트에서 비밀번호 관리를 위해 Password Encoder를 사용하고 있습니다.
Password Encoder 구현체를 Bean에 등록하여 사용하기 위해 직접 DelegatingPasswordEncoder를 생성하여 Bean에 등록하였는데
Speing Security 5.0 이후부터는 DelegatingPasswordEncoder를 생성해주는 Factory 클래스가 추가되어 직접 생성할 필요가 없어졌기 때문에 해당 문서를 작성하였습니다.




Spring Security가 프로젝트에 적용되어있다면 다음과 같이 @Bean을 작성하기만 하면 됩니다.




@Configuration
public class SecurityConfiguration {

 @Bean
 public PasswordEncoder passwordEncoder() {
  return PasswordEncoderFactories.createDelegatingPasswordEncoder();
 }
}




사용할 때는 다음과 같이 사용할 수 있습니다.




class PasswordTests extends ApplicationTests {

 @Autowired
 PasswordService passwordTest;
 
 @Test
 void test() {
  String rawPassword = "비밀번호 입니다.";
  String encrypted = passwordTest.encrypt(rawPassword);

  assertThat(encrypted).contains("bcrypt");
  assertThat(passwordTest.match(rawPassword, encrypted)).isTrue();
 }

}

2019년 9월 30일 월요일

[Selenium] 1. Java와 Firefox를 이용하여 Google검색 자동화 하기

개요

Selenium은 브라우저를 자동화 할 수 있는 도구이며
일반적으로 이를 이용하여 자동화 테스트를 수행하거나 웹 크롤링 등을 수행할 수 있습니다.

해당 가이드에서는 Java와 Selenium, Firefox Driver를 사용하여
구글에 접속 후 검색어를 입력하고 검색하는 테스트 코드를 작성합니다.

해당 가이드는 다음과 같은 준비물이 필요합니다.
  • Java JDK
  • Eclipse IDE
  • Firefox Web Browser (다른 브라우저도 사용 가능하지만 해당 가이드에서는 Firefox를 이용한 방법을 다룹니다. Firefox외의 브라우저는 https://www.seleniumhq.org/download/에서 해당 브라우저에 맞는 Web Driver를 찾으시길 바랍니다.)

프로젝트 생성

예제 작성을 위한 프로젝트를 생성합니다.
메뉴의 File - New - Project...를 클릭한 뒤 Maven Project를 선택합니다.
Eclipse New Project Window
아래와 같이 프로젝트 정보를 입력한 후 프로젝트를 생성합니다.
Eclipse New Maven Project Window

Web Driver 다운로드

https://github.com/mozilla/geckodriver/releases에 접속하여 자신의 OS에 맞는 Firefox 드라이버를 다운로드 받습니다.
geckodriver releases Assets Download Page

다운받은 압축파일을 해제한 뒤 geckodriver 파일을 프로젝트의 resources 폴더로 이동시킵니다.
geckodriver on resources folder picture
geckodriver는 Linux 계열, geckodriver.exe는 Windows 계열 OS에서 사용 가능한 파일입니다. 필요한 Driver만 다운로드하여 추가하면 됩니다.

Selenium 의존성 추가

pom.xml 파일의 dependencies 태그 내에 다음 내용을 추가하여 Selenium을 사용하기 위한 Maven 의존성을 추가합니다.

<dependency>
 <groupId>org.seleniumhq.selenium</groupId>
 <artifactId>selenium-java</artifactId>
 <version>${selenium.version}</version>
</dependency>

Selenium은 문서 작성 기준 3.141.59버전을 사용했습니다.

자동화 테스트 작성

의존성 추가 후 Selenium을 테스트하는 간단한 예제를 작성해봅니다.

다음은 Firefox Driver를 생성하고
Google에 접속한 뒤 "Selenium WebDriver"검색하여 나온 결과를
로그에 소스 코드로 출력하는 예제입니다.

코드를 실행하기 전 GECKO_DRIVER_PATH를 resources 폴더에 추가한 geckodriver 파일명에 맞도록 수정해야 합니다.

package com.jeent.alcohol;

import java.nio.file.FileSystems;
import java.nio.file.Path;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

public class SeleniumTests {
 

public static final String DRIVER_PROPERTY = 
   "webdriver.gecko.driver";

 // TODO: resources 폴더 내의 geckodriver파일명에 맞춰 수정해줍니다.
public static final String GECKO_DRIVER_PATH = "src/main/resources/geckodriver.exe"; public static void main(String[] args) { Path path = FileSystems.getDefault().getPath(GECKO_DRIVER_PATH); System.setProperty(DRIVER_PROPERTY, path.toString()); WebDriver driver = new FirefoxDriver(); driver.get("https://www.google.com"); driver.findElement(By.name("q")).sendKeys("Selenium WebDriver"); driver.findElement(By.name("f")).submit(); new WebDriverWait(driver, 20).until( ExpectedConditions.visibilityOfElementLocated(By.id("resultStats"))); String source = driver.getPageSource(); System.out.println(source); } }

main 메서드를 실행하면 Firefox 브라우저가 실행되면서 예제 코드에서 작성한 동작이 수행되는 것을 확인할 수 있습니다.

Selenium을 활용하면 브라우저를 제어 할 수 있는 것 뿐만 아니라, 브라우저에 출력되는 내용을 읽어서 데이터화하는 크롤링 작업도 가능합니다.

다음 가이드에서는 예제에서 사용된 WebDriverWait 클래스의 용도를 자세히 알아보고 이어서 유튜브 재생목록을 크롤링하는 예제를 작성해 보도록 하겠습니다.

2019년 9월 26일 목요일

[CentOS8] Apache Tomcat 8 설치하기


해당 문서는 https://www.vultr.com/docs/how-to-install-apache-tomcat-8-on-centos-7 문서를 참고하여 작성되었습니다.





준비사항





  • Cent OS 7 또는 8 버전의 서버 또는 PC
  • sudo 권한을 갖는 계정




CentOS 시스템 업데이트





다음 명령어로 업데이트 및 재부팅을 실시합니다.





$ sudo yum install epel-release
$ sudo yum update -y && sudo reboot




재부팅이 완료되면 다음 단계로 진행합니다.





Java 설치하기





Apache Tomcat을 구동하기 위하여 Java SE 7.0 또는 이후 버전이 필요합니다. yum을 이용하여 OpenJDK를 설치합니다.





$ sudo yum install java-1.8.0-openjdk.x86_64




설치가 완료되면 아래의 명령어로 Java가 정상적으로 설치가 되었는지 확인할 수 있습니다.





$ java -version
openjdk version "1.8.0_222"
OpenJDK Runtime Environment (build 1.8.0_222-b10)
OpenJDK 64-Bit Server VM (build 25.222-b10, mixed mode)




Apache Tomcat 사용자 생성





보안상의 이유로 tomcat을 위한 non-root 사용자와 그룹을 생성해서 사용합니다.





$ sudo groupadd tomcat
$ sudo useradd -s /bin/nologin -g tomcat -d /opt/tomcat tomcat




해당 방법으로 시스템에 로그인할 수 없는 'tomcat' 그룹에 속한 'tomcat' 사용자를 작성합니다.
계정의 홈 경로는 /opt/tomcat이며 Apache Tomcat이 위치하게 될 경로입니다.





Apache Tomcat 다운로드 및 설치





https://tomcat.apache.org/download-80.cgi 링크로 이동하여 Tomcat 8의 안정된 최신 버전을 다운받을 수 있습니다.





Apache Tomcat 8 다운로드 페이지의 "Binary Distributions"의 "tar.gz"다운로드 링크를 복사한 후
아래처럼 wget 명령어를 이용하여 다운로드받습니다.





$ cd ~
$ wget http://mirror.navercorp.com/apache/tomcat/tomcat-8/v8.5.46/bin/apache-tomcat-8.5.46.tar.gz




다운받은 tar.gz파일을 tar 명령어를 이용하여 “tomcat" 사용자의 홈 경로에 압축을 해제합니다.





$ sudo tar -zxvf apache-tomcat-8.5.46.tar.gz -C /opt/tomcat --strip-components=1




권한 설정하기





Apache Tomcat을 실행하기 전 알맞은 권한 설정이 필요합니다.





$ cd /opt/tomcat
$ sudo chgrp -R tomcat conf
$ sudo chmod g+rwx conf
$ sudo chmod g+r conf/*
$ sudo chown -R tomcat logs/ temp/ webapps/ work/
$ sudo chgrp -R tomcat bin/ lib/
$ sudo chmod g+rwx bin
$ sudo chmod g+r bin/*




Systemd에 Tomcat Service 작성





시스템에 등록하여 톰캣을 시작 프로그램에 등록하고 명령어로 시작/정지/재시작을 할 수 있도록 설정합니다.





$ sudo vi /etc/systemd/system/tomcat.service




아래의 내용을 tomcat.service에 입력 후 저장합니다.
(일부 설정들은 환경에 맞게 수정해야 할 수 있습니다.)





[Unit]
Description=Apache Tomcat Web Application Container
After=syslog.target network.target
[Service]
Type=forking
Environment=JAVA_HOME=/usr/lib/jvm/jre
Environment=CATALINA_PID=/opt/tomcat/temp/tomcat.pid
Environment=CATALINA_HOME=/opt/tomcat
Environment=CATALINA_BASE=/opt/tomcat
Environment='CATALINA_OPTS=-Xms512M -Xmx1024M -server -XX:+UseParallelGC'
Environment='JAVA_OPTS=-Djava.awt.headless=true -Djava.security.egd=file:/dev/./urandom'
ExecStart=/opt/tomcat/bin/startup.sh
ExecStop=/bin/kill -15 $MAINPID
User=tomcat
Group=tomcat
[Install]
WantedBy=multi-user.target




haveged 설치하기(선택)





톰캣 시작 시 부팅 속도가 너무 느린 이슈를 해결하기 위해 haveged를 설치합니다.
자세한 내용은 tomcat, haveged 관한 다른 문서를 확인해주세요.





$ sudo yum install haveged
$ sudo systemctl start haveged.service
$ sudo systemctl enable haveged.service




Apache Tomcat 실행 및 테스트





Apache Tomcat을 실행한 뒤 시작 프로그램에 등록합니다.





$ sudo systemctl start tomcat.service
$ sudo systemctl enable tomcat.service




firewall-cmd를 이용하여 8080 포트를 열어 서버에 접근할 수 있도록 합니다.





$ sudo firewall-cmd --zone=public --permanent --add-port=8080/tcp
$ sudo firewall-cmd --reload




이후 8080 포트로 접속하면 Tomcat Welcome 페이지를 확인할 수 있습니다.
(로컬에서 테스트 중인 경우 localhost로 접속이 가능합니다.)





 예) http://localhost:8080 http://123.123.123.123:8080 (서버의 주소가 123.123.123.123일경우) 




설정이 전부 정상적으로 되었다면 웹 브라우저에 Tomcat Welcome 페이지가 정상적으로 출력됩니다.