浏览代码

[공통][New] 암호화(AES128) 모듈 추가

hyodong.min 7 年之前
父节点
当前提交
7872a0acf8

+ 6 - 1
app/src/main/java/kr/co/zumo/app/lifeplus/bean/MobileAuthBean.java

@@ -96,12 +96,17 @@ public class MobileAuthBean extends JsonBeanBase {
     this.nationality = nationality;
   }
 
+  /**
+   * 생년월일 8자리 (yyyyMMdd)
+   *
+   * @return
+   */
   public String getBirthDate() {
     return birthDate;
   }
 
   /**
-   * 생년월일 6자리 (YYMMDD)
+   * 생년월일 6자리 (yyMMdd)
    *
    * @return
    */

+ 73 - 0
app/src/main/java/kr/co/zumo/app/lifeplus/model/AES.java

@@ -0,0 +1,73 @@
+/*
+ * COPYRIGHT (c) 2018 All rights reserved by HANWHA LIFE.
+ */
+package kr.co.zumo.app.lifeplus.model;
+
+import android.util.Base64;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * AES
+ * <pre>
+ * </pre>
+ *
+ * @author 민효동
+ * @version 1.0
+ * @history 민효동   [2018. 12. 19.]   [최초 작성]
+ * @since 2018. 12. 19.
+ */
+public class AES {
+
+  /**
+   * AES 128 복호화
+   *
+   * @param text
+   * @param key
+   * @return
+   * @throws Exception
+   */
+  public static String decrypt(String text, String key) throws Exception {
+
+    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+    byte[] keyBytes = new byte[16];
+    byte[] b = key.getBytes("UTF-8");
+    int len = b.length;
+    if (len > keyBytes.length) { len = keyBytes.length; }
+    System.arraycopy(b, 0, keyBytes, 0, len);
+    SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
+    IvParameterSpec ivSpec = new IvParameterSpec(keyBytes);
+    cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
+
+    byte[] results = cipher.doFinal(Base64.decode(text, Base64.NO_WRAP));
+
+    return new String(results, "UTF-8");
+  }
+
+  /**
+   * AES 128 암호화
+   *
+   * @param text
+   * @param key
+   * @return
+   * @throws Exception
+   */
+  public static String encrypt(String text, String key) throws Exception {
+
+    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+    byte[] keyBytes = new byte[16];
+    byte[] b = key.getBytes("UTF-8");
+    int len = b.length;
+    if (len > keyBytes.length) { len = keyBytes.length; }
+    System.arraycopy(b, 0, keyBytes, 0, len);
+    SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
+    IvParameterSpec ivSpec = new IvParameterSpec(keyBytes);
+    cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
+
+    byte[] results = cipher.doFinal(text.getBytes("UTF-8"));
+
+    return Base64.encodeToString(results, Base64.NO_WRAP);
+  }
+}

+ 39 - 0
app/src/main/java/kr/co/zumo/app/lifeplus/model/BasicParamProvider.java

@@ -0,0 +1,39 @@
+/*
+ * COPYRIGHT (c) 2018 All rights reserved by HANWHA LIFE.
+ */
+package kr.co.zumo.app.lifeplus.model;
+
+import kr.co.zumo.app.lifeplus.util.AppUtil;
+
+/**
+ * BasicParamProvider
+ * <pre>
+ * </pre>
+ *
+ * @author 민효동
+ * @version 1.0
+ * @history 민효동   [2018. 12. 19.]   [최초 작성]
+ * @since 2018. 12. 19.
+ */
+public class BasicParamProvider implements IParamProvider {
+
+  @Override
+  public String getVersionName() {
+    return AppUtil.getVersionName();
+  }
+
+  @Override
+  public String getUserId() {
+    return SuperModel.getInstance().getUserId();
+  }
+
+  @Override
+  public String getDeviceId() {
+    return SuperModel.getInstance().getDeviceId();
+  }
+
+  @Override
+  public String getToken() {
+    return SuperModel.getInstance().getToken();
+  }
+}

+ 45 - 0
app/src/main/java/kr/co/zumo/app/lifeplus/model/IParamProvider.java

@@ -0,0 +1,45 @@
+/*
+ * COPYRIGHT (c) 2018 All rights reserved by HANWHA LIFE.
+ */
+package kr.co.zumo.app.lifeplus.model;
+
+/**
+ * IParamProvider
+ * - API 통신에 필요한 기본 정보를 제공해주는 객체의 인터페이스
+ * <pre>
+ * </pre>
+ *
+ * @author 민효동
+ * @version 1.0
+ * @history 민효동   [2018. 12. 19.]   [최초 작성]
+ * @since 2018. 12. 19.
+ */
+public interface IParamProvider {
+  /**
+   * App 버젼
+   *
+   * @return
+   */
+  String getVersionName();
+
+  /**
+   * User No
+   *
+   * @return
+   */
+  String getUserId();
+
+  /**
+   * Device ID
+   *
+   * @return
+   */
+  String getDeviceId();
+
+  /**
+   * Token
+   *
+   * @return
+   */
+  String getToken();
+}

+ 33 - 7
app/src/main/java/kr/co/zumo/app/lifeplus/model/module/APIModule.java

@@ -19,6 +19,8 @@ import io.reactivex.schedulers.Schedulers;
 import kr.co.zumo.app.R;
 import kr.co.zumo.app.lifeplus.bean.api.LifeplusAPIBean;
 import kr.co.zumo.app.lifeplus.bean.api.RequestBean;
+import kr.co.zumo.app.lifeplus.model.BasicParamProvider;
+import kr.co.zumo.app.lifeplus.model.IParamProvider;
 import kr.co.zumo.app.lifeplus.network.api.ParameterMapper;
 import kr.co.zumo.app.lifeplus.util.AppUtil;
 import kr.co.zumo.app.lifeplus.util.ResourceUtil;
@@ -192,16 +194,16 @@ public abstract class APIModule<T extends RequestBean, L extends LifeplusAPIBean
     return true;
   }
 
-  protected T mapBasicParameter(T requestBean) {
-    return new ParameterMapper<T>().map(requestBean);
+  private T mapBasicParameter(IParamProvider provider, T requestBean) {
+    return new ParameterMapper<T>().map(provider, requestBean);
   }
 
-  protected Disposable call(T requestBean, IAPISimpleModuleListener listener, Consumer<L> consumer) {
+  protected Disposable call(IParamProvider provider, T requestBean, IAPISimpleModuleListener listener, Consumer<L> consumer) {
     RxJavaPlugins.setErrorHandler(e -> {
-      Log.e("APP#  APIModule | call", "| > GLOBAL ERROR ->" + e.getLocalizedMessage());
+      Log.e("APP#  APIModule | call", "|                > GLOBAL ERROR ->" + e.getLocalizedMessage());
       new APIErrorConsumer(listener).accept(e);
     });
-    requestBean = mapBasicParameter(requestBean);
+    requestBean = mapBasicParameter(provider, requestBean);
     Log.d("APP# APIModule | call", "| <" + requestBean.getClass().getSimpleName() + ">");
     Log.d("APP# APIModule | call", "|" + APIModule.this.getClass().getSimpleName() + " -> " + requestBean.toPrettyJson());
 
@@ -234,7 +236,7 @@ public abstract class APIModule<T extends RequestBean, L extends LifeplusAPIBean
    * @return
    */
   public Disposable call(T requestBean, IAPIModuleListener<L> listener) {
-    return call(requestBean, listener, new APIConsumer(listener));
+    return call(new BasicParamProvider(), requestBean, listener, new APIConsumer(listener));
   }
 
   /**
@@ -245,7 +247,31 @@ public abstract class APIModule<T extends RequestBean, L extends LifeplusAPIBean
    * @return
    */
   public Disposable call(T requestBean, IAPISimpleModuleListener<L> listener) {
-    return call(requestBean, listener, new APISimpleConsumer(listener));
+    return call(new BasicParamProvider(), requestBean, listener, new APISimpleConsumer(listener));
+  }
+
+  /**
+   * API 를 호출한다.
+   *
+   * @param provider
+   * @param requestBean
+   * @param listener    IAPIModuleListener 3 가지 분기를 가진 리스너 success/reason/error
+   * @return
+   */
+  public Disposable call(IParamProvider provider, T requestBean, IAPIModuleListener<L> listener) {
+    return call(provider, requestBean, listener, new APIConsumer(listener));
+  }
+
+  /**
+   * API 를 호출한다.
+   *
+   * @param provider
+   * @param requestBean
+   * @param listener    IAPISimpleModuleListener 2 가지 분기를 가진 리스너 success/error
+   * @return
+   */
+  public Disposable call(IParamProvider provider, T requestBean, IAPISimpleModuleListener<L> listener) {
+    return call(provider, requestBean, listener, new APISimpleConsumer(listener));
   }
 
 }

+ 6 - 8
app/src/main/java/kr/co/zumo/app/lifeplus/network/api/ParameterMapper.java

@@ -4,8 +4,7 @@
 package kr.co.zumo.app.lifeplus.network.api;
 
 import kr.co.zumo.app.lifeplus.bean.api.RequestBean;
-import kr.co.zumo.app.lifeplus.model.SuperModel;
-import kr.co.zumo.app.lifeplus.util.AppUtil;
+import kr.co.zumo.app.lifeplus.model.IParamProvider;
 
 /**
  * ParameterMapper
@@ -25,12 +24,11 @@ public class ParameterMapper<T extends RequestBean> {
    * @param bean
    * @return
    */
-  public T map(T bean) {
-    SuperModel model = SuperModel.getInstance();
-    bean.setAppVersion(AppUtil.getVersionName());
-    bean.setUserNo(model.getUserId());
-    bean.setDeviceId(model.getDeviceId());
-    bean.setToken(model.getToken());
+  public T map(IParamProvider provider, T bean) {
+    bean.setAppVersion(provider.getVersionName());
+    bean.setUserNo(provider.getUserId());
+    bean.setDeviceId(provider.getDeviceId());
+    bean.setToken(provider.getToken());
     return bean;
   }
 }

+ 2 - 1
app/src/main/java/kr/co/zumo/app/lifeplus/supervisor/ContentsFlagHelper.java

@@ -20,6 +20,7 @@ import kr.co.zumo.app.lifeplus.bean.api.ContentsFlagResultBean;
 import kr.co.zumo.app.lifeplus.bean.api.ItemNumberBean;
 import kr.co.zumo.app.lifeplus.bean.api.LifeplusAPIBean;
 import kr.co.zumo.app.lifeplus.bean.api.RequestBean;
+import kr.co.zumo.app.lifeplus.model.BasicParamProvider;
 import kr.co.zumo.app.lifeplus.model.module.APIContentsBookmarkedModule;
 import kr.co.zumo.app.lifeplus.model.module.APIContentsLikedModule;
 import kr.co.zumo.app.lifeplus.model.module.APIError;
@@ -74,7 +75,7 @@ public class ContentsFlagHelper implements IFlags {
     }
     else {
       Log.w("APP# ContentsFlagHelper | load", "|" + "   new loading.........................");
-      single = new LifeplusAPIRepository().getContentsFlagList(new ParameterMapper<>().map(new RequestBean()))
+      single = new LifeplusAPIRepository().getContentsFlagList(new ParameterMapper<>().map(new BasicParamProvider(), new RequestBean()))
         .subscribeOn(Schedulers.io())
         .observeOn(AndroidSchedulers.mainThread())
         .doOnEvent((resultBean, throwable) -> {

+ 18 - 1
app/src/main/java/kr/co/zumo/app/lifeplus/view/screen/my/coin/CoinModelHelper.java

@@ -11,12 +11,17 @@ import java.util.List;
 import java.util.Map;
 
 import io.reactivex.disposables.Disposable;
+import kr.co.zumo.app.R;
 import kr.co.zumo.app.lifeplus.bean.api.CoinInfoBean;
 import kr.co.zumo.app.lifeplus.bean.api.CoinInfoResultBean;
 import kr.co.zumo.app.lifeplus.bean.api.RequestBean;
+import kr.co.zumo.app.lifeplus.model.AES;
+import kr.co.zumo.app.lifeplus.model.BasicParamProvider;
+import kr.co.zumo.app.lifeplus.model.IParamProvider;
 import kr.co.zumo.app.lifeplus.model.module.APICoInInfoLoadModule;
 import kr.co.zumo.app.lifeplus.model.module.APIError;
 import kr.co.zumo.app.lifeplus.model.module.IAPISimpleModuleListener;
+import kr.co.zumo.app.lifeplus.util.ResourceUtil;
 import kr.co.zumo.app.lifeplus.util.StringUtil;
 
 /**
@@ -100,7 +105,19 @@ public class CoinModelHelper {
     }
     else*/
     {
-      disposable = new APICoInInfoLoadModule().call(requestBean, new IAPISimpleModuleListener<CoinInfoResultBean>() {
+      IParamProvider provider = new BasicParamProvider() {
+        @Override
+        public String getUserId() {
+          try {
+            return AES.encrypt(super.getUserId(), ResourceUtil.getString(R.string.aes_key));
+          } catch (Exception e) {
+            e.printStackTrace();
+          }
+          return super.getUserId();
+        }
+      };
+
+      disposable = new APICoInInfoLoadModule().call(provider, requestBean, new IAPISimpleModuleListener<CoinInfoResultBean>() {
         @Override
         public void onApiSuccess(CoinInfoResultBean resultBean) {
           coinInfoBeans = resultBean.getData();

+ 2 - 0
app/src/main/res/values/config.xml

@@ -1,5 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
+  <string name="aes_key" translatable="false">ajA8iBc7fR+UgaQegns09B7W5GF</string>
+
   <string name="host_url" translatable="false">https://lifeplus.app</string>
   <string name="host_port" translatable="false">443</string>
   <string name="coop_url" translatable="false">https://lifeplus.multicon.co.kr</string>