[SpringConfig] Properties 암호화

JAVA/Spring|2019. 12. 24. 19:15

현재 토이 프로젝트에 Spring Cloud Config Server를 덕분에 설정을 편하게 사용하고 있습니다.

(config repo는 github를 사용하고 있는데 잘 되네요, 내역 관리도 되고 github 들어가서 수정하기도 편하니)

 

그런데 설정중에 암호에 대한 설정들이 있습니다.

 

현재는 혼자서 개발중이기 때문에 문제 없지만 공용 repo에 암호를 그대로 노출한다는게 조금 찝찝함은 있습니다.

 

그래서 미뤄놓았던것중 하나인 설정 암호화를 적용하려고 합니다.

 

설정 암호화는

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

 

ulisesbocchio/jasypt-spring-boot

Jasypt integration for Spring boot. Contribute to ulisesbocchio/jasypt-spring-boot development by creating an account on GitHub.

github.com

에 올라와있는 jasypt-spring-boot를 사용하여 처리하려고 합니다.

 

간단히 pom.xml에 해당 의존성을 추가하고

(최신버전이 3.0.0이네요)

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

 

properties에 암호화 키를

jasypt.encryptor.password= xxx 로 설정합니다.

 

그후에 StringEncryptor로 

 

    @Autowired
    StringEncryptor encryptor;

    @Test
    public void test(){

        String defaultStr = "aa131";

        String encrytStr = encryptor.encrypt(defaultStr);

        System.out.println("encrytStr : " + encrytStr);

        String decrytStr = encryptor.decrypt(encrytStr);
        System.out.println("decrytStr : " + decrytStr);

//        System.out.println("encrypt : " + encryptor.encrypt("a"));

    }

와 같이 암호화된 패스워드를 구합니다.

(org.jasypt.exceptions.EncryptionOperationNotPossibleException 와 같은 에러가 발생할 수 있는데, 검색해보시면 oracle에서 JCE 파일을 받아서 해결하는 방법을 찾을수 있습니다.)

암호화된 패스워드를 ENC() 로 감싸서 설정합니다.

 

spring.data.mongodb.password=ENC(xxxxxx)
jasypt.encryptor.password= xxx

설정을 변경후 기존 서버를 부팅시켜보면 정상적으로 동작하는것을 볼 수 있는데

 

같은 properties 파일에 암호키랑 암호화된 정보를 둘다 같고 있는건 조금 아니다 싶습니다.

 

그래서 어떻게 분리 시킬까 하다

저는 bootstrap.yml 에 

jasypt.encryptor.password 설정을 분리하고

properties에는 암호화된 값(ENC) 만 남겨 분리 했습니다.

jasypt:
  encryptor:
    password: xxxxxx

 

 

 

'JAVA > Spring' 카테고리의 다른 글

[Spring] LifeCycle, SmartLifeCycle  (0) 2020.06.23
[MSA] sidecar 패턴  (0) 2020.01.13
spring boot log level 변경(actuator)  (0) 2019.12.19
reactor Schedulers  (0) 2019.12.16
스프링 부트 2.2 릴리즈노트  (0) 2019.11.01

댓글()

spring boot log level 변경(actuator)

JAVA/Spring|2019. 12. 19. 19:50

로그레벨 동적 반영을 위하여

Controller를 하나 만들어서 처리할까 하다 이미 구현된 기능이 있을지 해서 검색해보니

이기 해당 기능이 actuator를 이용하여 처리가 가능하도록 되어있었습니다.

 

먼저 actuator를 사용하기 위해 pom.xml 에 추가합니다.(메이븐 기준으로)

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

 

설정 없이는 /actuator 로 확인할수 있는것들이 없지만 'management.endpoints.web.exposure.include' 에 항목들을 추가하여 추가적인 기능들을 사용할 수 있습니다.

management.endpoints.web.exposure.include=loggers

#management.endpoints.web.exposure.include=httptrace,loggers,health,info,metrics

 

logger 설정 및 확인을 위해 필요한 내용은 loggers입니다.

 

위와같이 설정 후 기동하게되면

'/actuator/loggers' 를 통해 모든 로거들의 로그레벨들을 확인할 수 있습니다.

 

 

'/actuator/loggers/로거명' 을 GET으로 요청하면 해당 로거만 나타나게 됩니다.

 

이제 목표인 로그레벨 동적 변경을 위해서는

'/actuator/loggers/로거명' 에 POST로 설정할 값을 보내주면 됩니다.

{"configuredLevel":null,"effectiveLevel":"INFO"} 를

{"configuredLevel":"ERROR","effectiveLevel":"ERROR"} 로 변경하고자 하면

 

헤더는 컨텐츠 타입을 application/json에 body에 {"configuredLevel":"ERROR","effectiveLevel":"ERROR"} 을 넣어 요청하도록 하면 됩니다.

 

 

 

'JAVA > Spring' 카테고리의 다른 글

[MSA] sidecar 패턴  (0) 2020.01.13
[SpringConfig] Properties 암호화  (0) 2019.12.24
reactor Schedulers  (0) 2019.12.16
스프링 부트 2.2 릴리즈노트  (0) 2019.11.01
[Spring] zuul 사용시 Eureka client로 분배가 안되는경우  (0) 2019.08.16

댓글()

reactor Schedulers

JAVA/Spring|2019. 12. 16. 20:47

Mono 혹은 Flux를 다룰때 map 혹은 subscribe 동작들을
subscribeOn()이나 publishOn()을 통해 다른 스레드에서 실행될 수 있도록 위임할수 있는데
인자는 Scheduler를 받습니다.


Spring WebFlux에서 Controller 스레드에서는 blocking 작업을 할수 없도록 되어있기에
필요한 경우에 subscribeOn() 를 사용하여 blocking 작업을 다른 스레드에서 사용할 수 있는데
Scheduler 종류마다 blocking 작업이 가능한 Scheduler가 있고 아닌 Scheduler 가 있습니다.
(non-blocking 스케줄은 블럭킹 작업이 불가능합니다.)





새로 신규로 생성하여 넘길수 있겠지만 Schedulers가 기본적으로 몇가지를 지원합니다.

  • parrallel
    • optimized for fast non-blocking executions
    • 속도 최적, non-blocking
  • single
    • optimized for low-latency one-off executions
    • 스레드 하나를 공유함, non-blocking
  • elastic
    • optimized for longer executions, alternative for blocking tasks where the number of active tasks can grow indefinitely
    • 긴작업에 최적, non-blocking 아님, blocking 작업 가능 스레드, 필요시 무한히 늘어남
  • boundedElastic
    • optimized for longer executions, alternative for blocking tasks where the number of active tasks is capped
    • 긴작업에 최적, non-blocking 아님, blocking 작업 가능 스레드, 정해진 사이즈
  • immediate
    • to run a task on the caller Thread
    • 콜러 스레드에서 실행
  • fromExecutorService
    • 기존 java.util.concurrent.Executors 를 활용

댓글()

JEP 218: Generics over Primitive Types

JAVA|2019. 12. 10. 19:23

이전에

List list = new ArrayList<>();

list.add(3);

int val = list.get(0);

에 대한 질문을 본적이 있습니다.

현재(지금까지 접했던)까지의 Java는 Generic에 primitive인 가 아닌 로 적어야 맞는것

그리고 list.add(3); 에서 auto-boxing 에 대해 언급했었습니다.

그리고 int val = list.get(0); 에서는 un-boxing이 일어나게 되죠

즉, 불필요한 객체가 생성되고 사라집니다.

검색을 하다보니 이부분을 "어쩔수 없다"가 아닌 해결해보려는 프로젝트가 있었습니다.

 

Valhalla 프로젝트

Valhalla 프로젝트에서는 크게 2가지 내용이 있었습니다.(https://openjdk.java.net/projects/valhalla/)

  • Value Types
  • Generic Spcialization(JEP 218)

그중 Generic Spcialization(JEP 218) 가 Generics over Primitive Types 에 다루고 있는 항목이였습니다.
https://openjdk.java.net/jeps/218

 

JEP 218: Generics over Primitive Types

JEP 218: Generics over Primitive Types Summary Extend generic types to support the specialization of generic classes and interfaces over primitive types. Goals Generic type arguments are constrained to extend Object, meaning that they are not compatible wi

openjdk.java.net

JEP(JDK Enhancement Proposal) 내용이기 때문에 언제 이루어질지 알수 없지만

하나씩 하나씩 추가되고 개선될때마다, 코틀린이나 스칼라가 아닌 자바

그 자체로 간편하고 더더욱 효율적인 언어가 될것을 기대한다.

 

 

'JAVA' 카테고리의 다른 글

SortedQueue...  (0) 2020.07.02
java.util.function 인터페이스  (0) 2019.12.30
[CompletableFuture][#3] 메소드 정리-1  (0) 2019.09.01
[Quartz] Trigger  (0) 2019.07.10
[CompletableFuture][#2] staticMethod  (0) 2019.07.09

댓글()

스프링 부트 2.2 릴리즈노트

JAVA/Spring|2019. 11. 1. 18:20

한 달 동안 잠시 해외를 다녀온 사이 Spring Boot 2.2가 릴리즈 되었습니다.
지금까지 버전업 되면서 변경 사항들을 모두 파악하지는 못했지만
계속 사용하게될 SpringBoot이기 때문에 2.1x에서 2.2x로 올라가며 변경돼 사항을 파악하고자
릴리즈 노트를 번역 및 개인적으로 궁금한 사항을 파악해보았습니다.

릴리즈 정보 출처

https://spring.io/blog/2019/10/16/spring-boot-2-2-0
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.2-Release-Notes


스프링 관련 프로젝트 업데이트

  • Spring AMQP 2.2
  • Spring Batch 4.2
  • Spring Data Moore
  • Spring Framework 5.2
  • Spring HATEOAS 1.0
  • Spring Integration 5.2
  • Spring Kafka 2.3
  • Spring Security 5.2
  • Spring Session Corn

서드 파티 라이브러리 업데이트

  • Elasticsearch 6.7
  • Flyway 6.0
  • Jackson 2.10
  • JUnit 5.5
  • Micrometer 1.3
  • Reactor Dysprosium
  • Solr 8.0

성능 개선

SpringBoot2.1보다 2.2에서는 더 빠른 시작과 더 적은 메모리 사용량을 보여줄 것이며 특히 타이트한 메모리 환경에서 유용할 것입니다.

초기화 지연(Lazy initialization)

spring.main.lazy-initialization 속성을 통해 전역으로 lazy init을 활성화시킬 수 있습니다.
초기화를 늦춤에 따라 아래의 추가적인 비용들이 발생합니다.

Java13 지원

Spring 5.2가 Java 13을 지원함에 따라 Spring Boot2.2도 Java 13을 지원하며, Java11과 Java8 또한 지원합니다.

@ConfigurationProperties 생성자 바인딩 지원

설정 properties는 이제 생성자 바인딩을 지원하기 때문에 클래스의 불변을 지원합니다.
@ConfigurationProperties를 붙이거나, @ConstructorBinding를 붙이면 생성자 바인딩이 활성화되며, @DefaultValue와 @DateTimeFormat 이 생성자 바인딩으로 동작합니다.

RSocket 지원

RSocket에 대한 자동 설정을 지원합니다. spring-boot-starter-rsocket

 

수정 중이며 잘못된 내용이 있으면 의견 부탁드립니다.

감사합니다.

댓글()

[CompletableFuture][#3] 메소드 정리-1

JAVA|2019. 9. 1. 20:40

지난번에 static 메소드를 정리해보았고

이제 CompletableFuture(이하 cf)의 메소드에 대해 정리해보려고 합니다.

정리하려고 public 메소드를 뽑아보았더니...

굉장히 길었습니다..

그래서 조금 나누어 정리해야 할것 같아 메서드 네이밍을 쭉 살펴보니

크게 두가지로 나눠 보았습니다.

  • 실행 후 제어(thenRun, handle....)
    • sync
      • acceptEither
      • applyToEither
      • handle
      • runAfterBoth
      • runAfterEither
      • thenAccept
      • thenAcceptBoth
      • thenApply
      • thenCombine
      • thenCompose
      • thenRun
      • whenComplete
    • async
      • acceptEitherAsync
      • applyToEitherAsync
      • handleAsync
      • runAfterBothAsync
      • runAfterEitherAsync
      • thenAcceptAsync
      • thenAcceptBothAsync
      • thenApplyAsync
      • thenCombineAsync
      • thenComposeAsync
      • thenRunAsync
      • whenCompleteAsync
  • async 한 작업을 대기하거나 상태를 확인 및 기타등등(get, isDone, join ....)
    • cacel
    • complete
    • completeExceptionally
    • exceptionally
    • get()
    • get(time)
    • getNow
    • getNumberOfDependents
    • isCancelled
    • isCompletedExceptionally
    • isDone
    • join
    • obtrudeException(Throwable)
    • obtrudeValue(R)

먼저 "실행 후 제어(thenRun, handle....)" 메서드 를 살펴보겠습니다.

위에 정리한것처럼 Async 가 붙은것 붙지 않은것이 각각 존재 합니다.

아직 다 살펴보지 않아 정확하지는 않지만 async가 메소드명에 붙고 안붙는것에 따라 sync/async가 갈릴것으로 파악 됩니다.

하나씩 살펴보겠습니다.

acceptEither

applyToEither

handle

runAfterBoth

runAfterEither

thenAccept

thenAcceptBoth

thenApply

thenCombine

thenCompose

thenRun

whenComplete

Async

acceptEitherAsync
applyToEitherAsync
handleAsync
runAfterBothAsync
runAfterEitherAsync
thenAcceptAsync
thenAcceptBothAsync
thenApplyAsync
thenCombineAsync
thenComposeAsync
thenRunAsync
whenCompleteAsync

Util
cacel
complete
completeExceptionally
exceptionally
get()
get(time)
getNow
getNumberOfDependents
isCancelled
isCompletedExceptionally
isDone
join
obtrudeException(Throwable)
obtrudeValue(R)

'JAVA' 카테고리의 다른 글

java.util.function 인터페이스  (0) 2019.12.30
JEP 218: Generics over Primitive Types  (0) 2019.12.10
[Quartz] Trigger  (0) 2019.07.10
[CompletableFuture][#2] staticMethod  (0) 2019.07.09
[CompletableFuture][#1] 정리시작  (0) 2019.07.03

댓글()

[Spring] zuul 사용시 Eureka client로 분배가 안되는경우

JAVA/Spring|2019. 8. 16. 19:56

Toy 프로젝트에 zuul 을 적용해서 사용해보고있는데

여러 appSvr를 EurekaServer에 붙이고 zuul로 호출해봤으나 이상하게도

하나의 appSvr로 호출되는 현상이 발생했습니다.

 

이게 원래 그런가?(active-standby로..?) 라고 처음에는 생각해봤지만 그건 너무 아닌것 같아서

이런저런 시도를 하다 eureakServer에 /eureka/apps 로 등록된 app을 확인해보니

zuul(API-GATEWAY)이랑 appSvr(MEMBER-API 라는 샘플..)이 정상적으로 등록되어있지만

appSvr가 3개가 나타나야 하는데 하나만 나타나는것을 확인했습니다.

 

등록된 정보들을 살펴보다가 떠오른것이..

eureka.instanceId 설정을.. 안했...네요..

 

설정을 안하다보니, ip:applicationName:port 으로 instanceId가 다 지정되어

(port는 일부러 random으로 띄우기 위해 0으로 설정했었습니다.)

동일한 instanceId 로 등록을 시도하고 있었던것 이였습니다.

 

그래서 'eureka.instance.instance-id' 설정을 추가해주었고

설정값은 'hostname:applicationname:springinstanceId:random값'

으로 하여 중복이 발생하지 않고 기존처럼 인식할수 있도록 변경하였습니다.

 

eureka.instance.instance-id=${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${random.value}}

 

간단한 설정 실수였지만.. 역시 reference 를 잘 읽어야.. 하겠습니다.

 

요약

1. eureka.instance.instance-id 를설정하지 않거나 중복 된다면 제대로 동작 안할수 있다.

 

 

 

댓글()

[Spring] JDBC Template 어떻게 Thread-Safe 할까?

JAVA/Spring|2019. 8. 6. 18:27

Spring 스터디중 나온 질문 입니다.

 

DAO 클래스를 만들때 "JDBC Template"는 new 해서 사용하기도 하지만, "Thread-Safe 하기 때문에 빈으로 등록해서 사용할 수 있다"

 

Toy 프로젝트 때는 MyBatis를 쓰거나, JPA를 사용하기 때문에 JDBC Template를 사용할 일이 많지 않았지만,

대체 내부 구조가 어떻게 되어있길래 Thread-Safe한거지? 라는 의문이 들었습니다.

(JDBC에 Connection, Statement, ResultSet 은 Thread-Safe 하지 않기 때문에..)

 

예상 할 수 있는건

락(sync)를 잡아 처리 하나? 아니면 ThreadLocal로 처리하나?

정도로 예상해볼수 있는데 락잡아 처리한다면.. 쫌 아닐꺼라 생각되지만 코드를 살펴봤습니다.

JdbcTemplate의 query, update, execute 등 대부분의 메소드들은 살펴보면 메소드 내에서

DataSourceUtils.getConnection(ds) 를 통해 Connection을 얻어오고 있으며

메소드에서 생성된 ps나 rs 그리고 connection(물론 connection은 무조건 정리하지는 않습니다.) 정리 하고 있습니다.

//즉, JdbcTemplate 객체에 상태 변화 없이 메소드 내에서 모든 리소스가 정리 됨

 

JdbcTemplate 객체내에서 리소스(예를 들어 Connection)를 정리하지 않고 보존해야 하는경우도 있는데

(예를 들어 @Transaction)

그경우를 위해 DataSourceUtils.getConnection(ds) 코드를 따라가보면

TransactionSynchronizationManager.getResource(ds)를 통해 ConnectionHolder를 가져오는데

TransactionSynchronizationManager.getResource(ds)를 더 들어가보면

ThreadLocal<Map<Object,Object>>로 되어있는 resources를 가져와 ds를 키로 ConnectionHolder를 가져오는것을 볼수 있었습니다.

 

 

 

결론

1. JdbcTemplate 인스턴스는 상태를 갖지 않고 메소드 내에서 생성된 리소스(rs, ps, connection) 들을 정리하기 때문에 Thread-Safe하다

2. Transaction이 필요한경우 정리하면 안되는 Connection의 경우 JdbcTemplate이 상태를 가지지 않고TransactionSynchronizationManager에 ThreadLocal로 보관 하기 때문에 JdbcTemplate를 Thread-Safe하며,

Connection 객체 전달 및 전파 필요 없이 트랜잭션 제어를 하기 용이 하다.

 

 

댓글()