스프링2023. 1. 28. 18:41

스프링 부트

 스프링 부트 소개 스프링 부트(Spring Boot)는 스프링을 기반으로 실무 환경에 사용 가능한 수준의 독립실행 형 애플리케이션을 복잡한 고민 없이 빠르게 작성할 수 있게 도와주는 여러가지 도구의 모음 이다.

스프링 부트의 핵심 목표

  • 매우 빠르고 광범위한 영역의 스프링 개발 경험을 제공
  • 강한 주장(권고)을 가지고 즉시 적용 가능한 기술 조합을 제공하면서, 필요에 따라 원하는 방 식으로 손쉽게 변형 가능
  • 프로젝트에서 필요로 하는 다양한 비기능적인 기술(내장형 서버, 보안, 메트릭, 상태 체 크, 외부 설정 방식 등) 제공
  • 코드 생성이나 XML 설정을 필요로 하지 않음
설정에 너무 신경 쓰지말고 서비스에 집중해라.

 

 

 

Posted by 미랭군
스프링2023. 1. 16. 16:03

1. Jasypt

Jasypt(Java Simplified Encryption)는 개발자가 암호화 작동 방식에 대한 깊은 지식 없이도 최소한의 노력으로 자신의 프로젝트에 기본 암호화 기능을 추가할 수 있도록 하는 Java 라이브러리이다.

2. 암호화 설정

1) Dependency 추가

  • 설정파일 암호화
<dependency>
    <groupId>com.github.ulisesbocchio</groupId>
    <artifactId>jasypt-spring-boot-starter</artifactId>
    <version>3.0.3</version>
</dependency>
 
  • 암호 알고리즘
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.69</version>
</dependency>
 

2) PBEWithMD5AndDES 알고리즘 사용

  • JasyptConfigDES.java
import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties;
import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableEncryptableProperties
public class JasyptConfigDES {

    @Bean("jasyptEncryptor")
    public StringEncryptor stringEncryptor() {
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        SimpleStringPBEConfig config = new SimpleStringPBEConfig();
        config.setPassword("password"); // 암호화 키
        config.setAlgorithm("PBEWithMD5AndDES"); // 알고리즘
        config.setKeyObtentionIterations("1000");
        config.setPoolSize("1");
        config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
        config.setStringOutputType("base64");
        encryptor.setConfig(config);
        return encryptor;
    }
}
 
  • 테스트
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;

public class DESEncyptTest {

    public static void main(String[] args) {
        StandardPBEStringEncryptor pbeEnc = new StandardPBEStringEncryptor();
        pbeEnc.setAlgorithm("PBEWithMD5AndDES");
        pbeEnc.setPassword("password");

        String enc = pbeEnc.encrypt("plain_text");
        System.out.println("enc = " + enc);

        String des = pbeEnc.decrypt(enc);
        System.out.println("des = " + des);
    }
}
 

3) PBEWithSHA256And128BitAES-CBC-BC 알고리즘 사용

SHA256, AES128 사용을 위해 BouncyCastle 라이브러리를 사용한다. BouncyCastle은 PBE(Password Based Encryption)에 보다 많은 알고리즘을 제공해 준다.

  • JasyptConfigAES.java
import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableEncryptableProperties
public class JasyptConfigAES {

    @Bean("jasyptEncryptor")
    public StringEncryptor stringEncryptor() {
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        encryptor.setProvider(new BouncyCastleProvider());
        encryptor.setPoolSize(2);
        encryptor.setPassword("password"); // 암호화 키
        encryptor.setAlgorithm("PBEWithSHA256And128BitAES-CBC-BC"); // 알고리즘

        return encryptor;
    }
}
 
  • 테스트
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;

public class AESEncyptTest {

    public static void main(String[] args) {
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        encryptor.setProvider(new BouncyCastleProvider());
        encryptor.setPoolSize(2);
        encryptor.setPassword("password");
        encryptor.setAlgorithm("PBEWithSHA256And128BitAES-CBC-BC");

        String plainText = "plain_text";
        String encryptedText = encryptor.encrypt(plainText);
        String decryptedText = encryptor.decrypt(encryptedText);
        System.out.println("Enc = " + encryptedText);
        System.out.println("Dec = " + decryptedText);
    }
}
 

3. properties 파일 적용

properties 파일에 암호화 bean 이름과 암호화된 내용을 작성한다.

  • application.properties
jasypt.encryptor.bean=jasyptEncryptor

spring.datasource.driver-class-name=net.sf.log4jdbc.sql.jdbcapi.DriverSpy
spring.datasource.jdbc-url=ENC(OCVOlP4CAmC/49yWqP4rn/6ZKuleEtEyLJNUh5KjuJEfGzd4iGrFMShHVjoCL6GCeCK9jmArUZO/G7F0jQmsarR6TYMUwag6trEv33e3tcs=)
spring.datasource.username=ENC(MHEf37ImCLMjbioeXLqYCRpgyjUAcZAo88Nq9NbCd4I=)
spring.datasource.password=ENC(BbJAsSr4uISv+mTAw2fN+UTy2dodoDh3++YchPhw5qI=)
 

[출처 및 참고]

Posted by 미랭군
스프링2022. 5. 25. 12:59

authenticated()와 permitAll()는 보안이 필요한 패스를 정의하기 위해 사용된다.

authenticated() 메소드는 애플리케이션에 로그인된 사용자가 요청을 수행할 떄 필요하다. 만약 사용자가 인증되지 않았다면, 스프링 시큐리티 필터는 요청을 잡아내고 사용자를 로그인 페이지로 리다이렉션 해준다.

permitAll() 메소드는 어떠한 보안 요구 없이 요청을 허용해준다.

Posted by 미랭군
스프링2021. 3. 7. 22:42
Posted by 미랭군
스프링2012. 8. 31. 17:27

BeanFactory = ApplicationContext = IoC Container = Spring Container 가 생성/관리하는 빈 오브젝트는 


특별한 설정이 없는 한,  (빈의 scope이  prototype scope, request scope, session scope 이 아닌 이상..)


싱글톤 오브젝트이다.

이러한 이유로 Spring Container을 Sigleton Registry 라고도 부른다.


한 가지 기억해둘 것은 ..


빈으로 등록되는 클래스가 디자인 패턴의 하나인 Singleton pattern을 적용한 클래스가 아니다라는 점


빈으로 등록되는 클래스는 (private 생성자, public static getInstance() 메소드등이 없는) 평범한 클래스이다. 


이 평범한 클래스를 빈 컨테이너가 관리하면.. Singleton object가 된다


또 한 가지 더 기억해둘 것은 ..


빈으로 등록할 클래스는 Singleton Object가 되기 때문에.. 


stateless 방식으로 만들어야 된 다는 점, 


이유는 멀티쓰레드 환경에서 하나의 Object를 공유할 때 발생할 문제들을 애초에 없애기 위함이다.

Posted by 미랭군
스프링2012. 8. 10. 11:45

<서론>

스프링 @MVC에서 ContentsNagotiator에서 JacksonJsonView로 자동으로 JSON으로 결과물을 생성되게 만들었습니다.
그과정에서 한가지 이슈가 있었습니다.
무엇이냐면 JSON을 리턴할때 무조건 객체가 2depth 이상으로 생성이 된다는 것입니다.

만약 컨트롤러에 아래와 같은 코드가 있다면,

   1: ModelAndView mav = new ModelAndView();
   2: mav.addObject(listOfObjects);
   3: return mav;

아래와 같은 JSON이 생성이 됩니다.


   1: {"objectList" : [{"name":"object1"}, {"name":"object2"}]}

그러나 제가 원하는 JSON은 아래와 같습니다.


   1: [{"name":"object1"}, {"name":"object2"}]


 

<본론>
해결 방안은 기본 JacksonJsonView를 상속하여 filterModel함수를 오버라이딩 하는 것입니다.


   1: import java.util.Map;
   2: import org.springframework.web.servlet.view.json.MappingJacksonJsonView;
   3:  
   4: public class MappingJacksonJsonViewEx extends MappingJacksonJsonView
   5: {
   6:     @SuppressWarnings("unchecked")
   7:     @Override
   8:     protected Object filterModel(Map<String, Object> model) {
   9:  
  10:         Object result = super.filterModel(model);
  11:         if (!(result instanceof Map)) {
  12:             return result;
  13:         }
  14:         Map map = (Map) result;
  15:         if (map.size() == 1) {
  16:             return map.values().toArray()[0];
  17:         }
  18:         return map;
  19:     }
  20: }

ApplicationContext에 설정하는 내용은 (완전한 내용을 포함하진 않았지만) 아래와 같이 됩니다.


   1: <-- default view-->
   2: <property name="defaultViews">
   3:     <list>
   4:         <ref bean="xmlView" />
   5:         <ref bean="jsonView" />
   6:     </list>
   7: </property>
   8:  
   9: <!-- JSON marshalling view -->
  10: <bean id="jsonView" class="ks.spring.sample.MappingJacksonJsonViewExtension" >
  11:     <property name="renderedAttributes" value="restRoot" />
  12: </bean>


 

<결론>

JSON을 한 depth 밖으로 빼내기 위해서, JacksonJSON Viewer의 기본 Filter를 변경시키는 것입니다.

'스프링' 카테고리의 다른 글

SecurityConfig  (0) 2022.05.25
Spring Boot Sample  (0) 2021.03.07
Singleton Registry = ApplicationContext의 또 다른 이름  (0) 2012.08.31
Spring Security - username 정보 가져오기  (0) 2012.01.09
Role in Spring security  (0) 2011.05.18
Posted by 미랭군
스프링2012. 1. 9. 17:18
아래와 같이 하면 Spring Security를 사용할 때 User와 관련된 정보(username, password, authorities)를 얻어올 수 있다.

User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
System.out.println("username = " + user.getName());

Posted by 미랭군
스프링2011. 5. 18. 14:27

Spring Security에서 role은 기본적으로 "ROLE_"로 시작해야 한다. 그렇지 않으면 오류를 뱉어낸다. 만약 "PRIV_" 등 다른 접두사를 사용하거나 특별한 네임 규칙이 없는 다른 role명을 사용하던 기존 시스템에 Spring Security를 연결해야 한다면 추가적인 설정이 필요하다.

다음과 같이 Access Decision Manager를 정의하고, RoleVoter에 prefix를 재설정하면 된다.
<security:http auto-config="true"
    access-decision-manager-ref="accessDecisionManager">
...
</security:http>

<bean id="accessDecisionManager"
    class="org.springframework.security.vote.AffirmativeBased">
  <property name="allowIfAllAbstainDecisions" value="false" />
  <property name="decisionVoters">
    <list>
      <bean class="org.springframework.security.vote.RoleVoter">
        <property name="rolePrefix" value="" /> <-- ROLE_ -->
      </bean>
    </list>
  </property>
</bean>
Posted by 미랭군