Commit e937e0fc authored by mengcuiguang2's avatar mengcuiguang2

Merge branch 'dev_ad'

parents 2ebe1a42 174bae57
......@@ -134,7 +134,7 @@ android {
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation fileTree(include:['*.jar'], dir:'libs')
testImplementation rootProject.ext.support["junit"]
//下拉刷新
......@@ -162,8 +162,9 @@ dependencies {
// 应用管理中心分包
implementation(name: 'humesdk-1.0.0', ext: 'aar')
// umeng
implementation(name: 'umeng-asms-armeabi-v1.2.2', ext: 'aar')
implementation(name: 'umeng-apm-armeabi-v1.2.0', ext: 'aar')
implementation 'com.umeng.umsdk:common:9.4.0'// 必选
implementation 'com.umeng.umsdk:asms:1.2.3'// 必选
implementation 'com.umeng.umsdk:apm:1.4.0'
// 穿山甲 GroMore
// mediation_ad_sdk
implementation(name: 'mediation_ad_sdk_2.8.1.0', ext: 'aar')
......@@ -178,7 +179,6 @@ dependencies {
//RxPay
implementation 'com.cuieney:rxpay-api:2.2.3'
kapt 'com.cuieney:rxpay-compiler:2.1.1'
implementation 'com.romandanylyk:pageindicatorview:1.0.3'
implementation(name: 'BaiduLBS_AndroidSDK_Lib', ext: 'aar')
......
......@@ -410,6 +410,35 @@
# ======================= 穿山甲 GroMore END ================
# ===================== RxPay START ================
-keep class com.alipay.android.app.IAlixPay{*;}
-keep class com.alipay.android.app.IAlixPay$Stub{*;}
-keep class com.alipay.android.app.IRemoteServiceCallback{*;}
-keep class com.alipay.android.app.IRemoteServiceCallback$Stub{*;}
-keep class com.alipay.sdk.app.PayTask{ public *;}
-keep class com.alipay.sdk.app.AuthTask{ public *;}
-keep class com.alipay.sdk.app.H5PayCallback {
<fields>;
<methods>;
}
-keep class com.alipay.android.phone.mrpc.core.** { *; }
-keep class com.alipay.apmobilesecuritysdk.** { *; }
-keep class com.alipay.mobile.framework.service.annotation.** { *; }
-keep class com.alipay.mobilesecuritysdk.face.** { *; }
-keep class com.alipay.tscenter.biz.rpc.** { *; }
-keep class org.json.alipay.** { *; }
-keep class com.alipay.tscenter.** { *; }
-keep class com.ta.utdid2.** { *;}
-keep class com.ut.device.** { *;}
-dontwarn com.alipay.**
# ======================= RxPay END ================
# ===================== 百度地图 START ================
-keep class com.baidu.** {*;}
-keep class vi.com.** {*;}
......
......@@ -20,15 +20,14 @@
<!-- 调用相机,用于实现扫描二维码,预览个性化地图编辑器生成的个性化地图样式(开发者实际开发中地图SDK不需要该权限)-->
<uses-permission android:name="android.permission.CAMERA" />
<application
android:name="com.mints.street.AppApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:icon="@mipmap/ic_launcher_main"
android:label="@string/app_name"
android:largeHeap="true"
android:networkSecurityConfig="@xml/network_security_config"
android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
......@@ -67,20 +66,25 @@
android:process=":remote"/>
<activity android:name="com.mints.street.splash.SplashActivity"
android:excludeFromRecents="true"
android:theme="@style/NormalSplash">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="um.60e80209a6f90557b7b19aa7" />
</intent-filter>
</activity>
<activity android:name="com.mints.street.login.LoginActivity">
</activity>
<activity android:name="com.mints.street.main.MainActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:excludeFromRecents="true"
android:launchMode="singleTask"
android:theme="@style/AppTheme.NoneTranslucent">
......@@ -88,6 +92,7 @@
<activity android:name=".main.my.MoresettingsActivity"/>
<activity android:name=".main.my.AboutusActivity"/>
<activity android:name=".main.my.PermissionsActivity"/>
<activity android:name=".main.home.HistoricalimageActivity"/>
<!-- ShareSDK start -->
<activity
......
......@@ -33,14 +33,14 @@ class AppApplication : BaseApp() {
builder.detectFileUriExposure()
// 解决java.util.concurrent.TimeoutException https://www.jianshu.com/p/844ef9c84f15
val defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()
Thread.setDefaultUncaughtExceptionHandler { t, e ->
if (t.name == "FinalizerWatchdogDaemon" && e is TimeoutException) {
Log.e("ignore", "ignore")
} else {
defaultUncaughtExceptionHandler?.uncaughtException(t, e)
}
}
// val defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()
// Thread.setDefaultUncaughtExceptionHandler { t, e ->
// if (t.name == "FinalizerWatchdogDaemon" && e is TimeoutException) {
// Log.e("ignore", "ignore")
// } else {
// defaultUncaughtExceptionHandler?.uncaughtException(t, e)
// }
// }
}
/*
......
......@@ -2,7 +2,7 @@ package com.mints.street.api
import com.mints.street.bean.AwardBean
import com.mints.street.bean.UserBean
import com.mints.street.netwrok.HttpManager
import com.mints.street.netwrok.common.HttpManager
import io.reactivex.Observable
import me.goldze.mvvmhabit.http.BaseResponse
import retrofit2.Response
......
package com.mints.street.login
import android.app.Application
import com.fry.base.basenetwork.HttpSubscribeImpl
import com.mints.street.bean.AwardBean
import com.mints.street.model.ApiModel
import com.mints.street.netwrok.base.HttpSubscribeImpl
import me.goldze.mvvmhabit.base.BaseViewModel
import me.goldze.mvvmhabit.http.BaseResponse
import me.goldze.mvvmhabit.utils.KLog
......@@ -26,7 +26,9 @@ class LoginViewModel(application:Application):BaseViewModel(application) {
override fun onBusinessSuccess(response: BaseResponse<AwardBean>) {
KLog.e("sfdsdf",response.result.toString())
}
override fun onBusinessFail(response: BaseResponse<AwardBean>?) {
}
})
}
}
\ No newline at end of file
......@@ -20,7 +20,7 @@ import com.mints.street.main.my.MyFragment
import com.mints.street.main.vr.VRFragment
import com.mints.street.manager.UmengManager
import com.tbruyelle.rxpermissions2.RxPermissions
import kotlinx.android.synthetic.main.layout_popupwindow.*
import com.umeng.analytics.MobclickAgent
import me.goldze.mvvmhabit.base.AppManager
import me.goldze.mvvmhabit.utils.ToastUtils
......@@ -69,6 +69,20 @@ class MainActivity : BaseActivity<ActivityMainBinding, MainViewModel>() {
}
override fun onResume() {
super.onResume()
// 友盟
MobclickAgent.onResume(this)
}
override fun onPause() {
super.onPause()
// 友盟
MobclickAgent.onPause(this)
}
var oldTime: Long = 0
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
when (keyCode) {
......
package com.mints.street.main.home
import android.os.Bundle
import android.view.View
import com.coorchice.library.utils.LogUtils
import com.fry.base.base.BaseActivity
import com.mints.street.BR
import com.mints.street.R
import com.mints.street.databinding.ActivityHistoricalImageBinding
import kotlinx.android.synthetic.main.activity_historical_image.*
import me.goldze.mvvmhabit.utils.ToastUtils
/**
* 描述:历史影像
* 作者:孟崔广
* 时间:2021/7/12 17:51
*/
class HistoricalimageActivity :BaseActivity<ActivityHistoricalImageBinding, HistoricalimageModel>(), View.OnClickListener {
override fun initVariableId() = BR.viewModel
override fun initContentView(savedInstanceState: Bundle?)= R.layout.activity_historical_image
override fun initData() {
super.initData()
initView()
}
private fun initView() {
}
override fun onClick(v: View?) {
}
}
package com.mints.street.main.home
import android.app.Application
import me.goldze.mvvmhabit.base.BaseViewModel
class HistoricalimageModel(application: Application): BaseViewModel(application) {
}
\ No newline at end of file
......@@ -16,6 +16,7 @@ import com.mints.street.BR
import com.mints.street.R
import com.mints.street.databinding.FragmentMyBinding
import com.mints.street.login.LoginActivity
import com.mints.street.main.home.HistoricalimageActivity
import kotlinx.android.synthetic.main.fragment_my.*
......@@ -73,7 +74,8 @@ class MyFragment : BaseFragment<FragmentMyBinding, MyViewModel>(), View.OnClickL
override fun onClick(v: View?) {
when (v?.id) {
R.id.ly_aboutus -> {
startActivity(AboutusActivity::class.java)
// startActivity(AboutusActivity::class.java)
startActivity(HistoricalimageActivity::class.java)
}
R.id.ly_moresettings -> {
startActivity(MoresettingsActivity::class.java)
......
......@@ -3,7 +3,7 @@ package com.mints.street.model
import com.mints.street.api.MainApi
import com.mints.street.bean.AwardBean
import com.mints.street.bean.UserBean
import com.mints.street.netwrok.HttpManager
import com.mints.street.netwrok.common.HttpManager
import com.trello.rxlifecycle2.LifecycleProvider
import io.reactivex.Observable
import me.goldze.mvvmhabit.http.BaseResponse
......
package com.fry.base.basenetwork;
package com.mints.street.netwrok.base;
import java.util.ArrayList;
import java.util.List;
......
package com.fry.base.basenetwork
package com.mints.street.netwrok.base
import me.goldze.mvvmhabit._enum.ViewStatus
import me.goldze.mvvmhabit.base.BaseViewModel
......
package com.fry.base.basenetwork;
package com.mints.street.netwrok.base;
import io.reactivex.disposables.Disposable;
import me.goldze.mvvmhabit.http.BaseResponse;
......
package com.fry.base.basenetwork
package com.mints.street.netwrok.base
import io.reactivex.Observer
import io.reactivex.disposables.Disposable
......
package com.fry.base.basenetwork;
package com.mints.street.netwrok.base;
import android.content.Context;
import android.text.TextUtils;
......@@ -6,6 +6,7 @@ import android.text.TextUtils;
import androidx.annotation.NonNull;
import com.fry.base.BuildConfig;
import com.mints.street.netwrok.common.GsonConverterFactory;
import java.util.concurrent.TimeUnit;
......@@ -15,7 +16,6 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import me.goldze.mvvmhabit.http.cookie.CookieJarImpl;
import me.goldze.mvvmhabit.http.cookie.store.PersistentCookieStore;
import me.goldze.mvvmhabit.http.interceptor.BaseInterceptor;
import me.goldze.mvvmhabit.http.interceptor.logging.Level;
import me.goldze.mvvmhabit.http.interceptor.logging.LoggingInterceptor;
import me.goldze.mvvmhabit.utils.Utils;
......@@ -25,7 +25,6 @@ import okhttp3.OkHttpClient;
import okhttp3.internal.platform.Platform;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
/**
* Created by jeme on 2019/1/31
......@@ -45,7 +44,6 @@ public class RetrofitClient {
throw new RuntimeException("baseUrl 不能为空");
}
SslHttpsUtils.SSLParams sslParams = SslHttpsUtils.getSslSocketFactory();
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()
.cookieJar(new CookieJarImpl(new PersistentCookieStore(mContext)))
// .cache(cache)
......
package com.mints.street.netwrok.common;
import com.google.gson.Gson;
import com.mints.street.manager.UserManager;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import me.goldze.mvvmhabit.http.BaseResponse;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import okio.Buffer;
import retrofit2.Converter;
import retrofit2.Retrofit;
/**
* Description:gson全局解析
*/
public class GsonConverterFactory extends Converter.Factory {
private final Gson gson;
public static GsonConverterFactory create() {
return create(new Gson());
}
public static GsonConverterFactory create(Gson gson) {
return new GsonConverterFactory(gson);
}
private GsonConverterFactory(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
this.gson = gson;
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
return new GsonResponseBodyConverter<>(gson, type);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
return new GsonRequestBodyConverter<>(gson, type);
}
// 这里创建从ResponseBody其它类型的Converter
// 主要用于对响应体的处理
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final Type type;
GsonResponseBodyConverter(Gson gson, Type type) {
this.gson = gson;
this.type = type;
}
@Override
public T convert(ResponseBody value) throws IOException {
Reader reader = value.charStream();
try {
T t = gson.fromJson(reader, type);
loginInvalid(t);
return t;
} finally {
try {
if (reader != null)
reader.close();
} catch (IOException ignored) {
ignored.printStackTrace();
}
}
}
/**
* 用户登陆失效
*
* @param t
*/
private void loginInvalid(T t) {
if (t instanceof BaseResponse) {
BaseResponse br = (BaseResponse) t;
int code = br.getstatus();
if (code == 401) {
try {
UserManager.Companion.getINSTANCE().userLogout();
// Activity forwardActivity = ForegroundOrBackground.getApp_activity();
// if (forwardActivity != null) {
// if (!forwardActivity.isFinishing()) {
// forwardActivity.startActivity(new Intent(forwardActivity, WxLoginActivity.class));
// }
// }
} catch (Exception e) {
}
}
}
}
}
// 在这里创建 从自定类型到ResponseBody 的Converter
// 主要用于对Part、PartMap、Body注解的处理
final class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
private final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
private final Charset UTF_8 = StandardCharsets.UTF_8;
private final Gson gson;
private final Type type;
GsonRequestBodyConverter(Gson gson, Type type) {
this.gson = gson;
this.type = type;
}
@Override
public RequestBody convert(T value) throws IOException {
Buffer buffer = new Buffer();
Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
gson.toJson(value, type, writer);
writer.flush();
return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
}
}
}
package com.mints.street.netwrok;
package com.mints.street.netwrok.common;
import io.reactivex.Observable;
......
package com.mints.street.netwrok;
package com.mints.street.netwrok.common;
import android.annotation.SuppressLint;
import com.fry.base.basenetwork.HttpConfiguation;
import com.fry.base.basenetwork.IHttpResponseListener;
import com.fry.base.basenetwork.RetrofitClient;
import com.fry.base.global.Constants;
import com.fry.base.netwrok.OkHttpInterceptor;
import com.mints.street.netwrok.base.HttpConfiguation;
import com.mints.street.netwrok.base.IHttpResponseListener;
import com.mints.street.netwrok.base.RetrofitClient;
import com.mints.street.utils.encry.AESUtils;
import com.trello.rxlifecycle2.LifecycleProvider;
......
package com.fry.base.netwrok
package com.mints.street.netwrok.common
import android.text.TextUtils
import android.util.Log
......@@ -165,6 +165,10 @@ class OkHttpInterceptor(aesKey: String) : Interceptor {
// 解密
try {
val json = JSONObject(rspString)
// if(!json.isNull("status")&& TextUtils.equals(json["status"].toString(),"401")){
// return
// }
if (!json.isNull("data")) {
val data = json["data"]
rspString = AESUtils.detrypt(data.toString(), aesKey)
......
......@@ -89,15 +89,16 @@ class SplashActivity:BaseActivity<ActivitySplashBinding,SplashViewModel>() {
if (!deviceInfo.signInfo) {
finish()
} else {
try {
mSplashContainer = findViewById(R.id.splash_container)
//加载开屏广告
loadSplashAd()
} catch (e: Exception) {
// try {
// mSplashContainer = findViewById(R.id.splash_container)
// //加载开屏广告
// loadSplashAd()
// } catch (e: Exception) {
// goToMainActivity()
// }
goToMainActivity()
}
}
}
/**
* 加载开屏广告
......
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="ViewModel"
type="com.mints.street.main.home.HistoricalimageModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent">
</LinearLayout>
</layout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
\ No newline at end of file
......@@ -8,6 +8,9 @@ buildscript {
maven { url "https://jitpack.io" }
google()
jcenter()
// umeng
maven { url 'https://repo1.maven.org/maven2/' }
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.1'
......@@ -27,6 +30,9 @@ allprojects {
google()
jcenter()
// umeng
maven { url 'https://repo1.maven.org/maven2/' }
}
}
......
package com.fry.base.basenetwork;
import java.lang.ref.WeakReference;
import io.reactivex.disposables.Disposable;
import me.goldze.mvvmhabit._enum.ViewStatus;
import me.goldze.mvvmhabit.base.BaseViewModel;
import me.goldze.mvvmhabit.http.BaseResponse;
import me.goldze.mvvmhabit.http.ExceptionHandle;
import me.goldze.mvvmhabit.http.ResponseThrowable;
import me.goldze.mvvmhabit.utils.ToastUtils;
import retrofit2.Response;
/**
* Created by jeme on 2019/1/31
*/
public abstract class HttpResponseListenerImpl<T extends BaseResponse> implements IHttpResponseListener<T>{
private WeakReference<BaseViewModel> viewModel;
private boolean needToast = true;
protected boolean isLoading = false;
public HttpResponseListenerImpl(BaseViewModel viewModel) {
this.viewModel = new WeakReference<>(viewModel);
}
public HttpResponseListenerImpl(BaseViewModel viewModel, boolean needToast) {
this.viewModel = new WeakReference<>(viewModel);
this.needToast = needToast;
}
public HttpResponseListenerImpl() {
}
@Override
public void onStart(Disposable disposable) {
if(!isLoading){
if(viewModel !=null && viewModel.get() != null){
viewModel.get().showDialog();
}
isLoading = true;
}else{
disposable.dispose();
}
}
@Override
public boolean onParseResponse(Response<T> response) {
return false;
}
public boolean isEmpty(T response){
return false;
}
@Override
public void onBusinessFail(T response) {
/* if(isEmpty(response)){
viewModel.get().viewSwitch(ViewStatus.NODATA);
}*/
if(response == null){
viewModel.get().viewSwitch(ViewStatus.NODATA);
return;
}
if(needToast) {
ToastUtils.showShort(response.getMessage());
}
}
@Override
public void onFailed(ResponseThrowable throwable) {
isLoading = false;
if(throwable == null){
return;
}
if(needToast) {
ToastUtils.showShort(throwable.message);
}
if(throwable.code == ExceptionHandle.ERROR.HTTP_ERROR
|| throwable.code == ExceptionHandle.ERROR.NETWORD_ERROR
|| throwable.code == ExceptionHandle.ERROR.TIMEOUT_ERROR){
if(viewModel != null && viewModel.get() != null){
viewModel.get().viewSwitch(ViewStatus.NONETWORK);
}
}
}
@Override
public void onCompleted() {
isLoading = false;
if(viewModel !=null && viewModel.get() != null){
viewModel.get().dismissDialog();
}
}
}
package com.fry.base.basenetwork;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
/**
* Created by ωǒ、〃尐川.η on 2018/8/20.
*/
public class HttpsUtil {
//获取这个SSLSocketFactory
public static SSLSocketFactory getSSLSocketFactory() {
try {
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, getTrustManager(), new SecureRandom());
return sslContext.getSocketFactory();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//获取TrustManager
private static TrustManager[] getTrustManager() {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
}
};
return trustAllCerts;
}
//获取HostnameVerifier
public static HostnameVerifier getHostnameVerifier() {
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
@Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
};
return hostnameVerifier;
}
}
package com.fry.base.basenetwork;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
/**
* Created by jeme on 2019/1/31
*/
public class SslHttpsUtils {
public static class SSLParams {
public SSLSocketFactory sSLSocketFactory;
public X509TrustManager trustManager;
}
public static SSLParams getSslSocketFactory() {
return getSslSocketFactoryBase(null, null, null);
}
/**
* https单向认证
* 可以额外配置信任服务端的证书策略,否则默认是按CA证书去验证的,若不是CA可信任的证书,则无法通过验证
*/
public static SSLParams getSslSocketFactory(X509TrustManager trustManager) {
return getSslSocketFactoryBase(trustManager, null, null);
}
/**
* https单向认证
* 用含有服务端公钥的证书校验服务端证书
*/
public static SSLParams getSslSocketFactory(InputStream... certificates) {
return getSslSocketFactoryBase(null, null, null, certificates);
}
/**
* https双向认证
* bksFile 和 password -> 客户端使用bks证书校验服务端证书
* certificates -> 用含有服务端公钥的证书校验服务端证书
*/
public static SSLParams getSslSocketFactory(InputStream bksFile, String password, InputStream... certificates) {
return getSslSocketFactoryBase(null, bksFile, password, certificates);
}
/**
* https双向认证
* bksFile 和 password -> 客户端使用bks证书校验服务端证书
* X509TrustManager -> 如果需要自己校验,那么可以自己实现相关校验,如果不需要自己校验,那么传null即可
*/
public static SSLParams getSslSocketFactory(InputStream bksFile, String password, X509TrustManager trustManager) {
return getSslSocketFactoryBase(trustManager, bksFile, password);
}
private static SSLParams getSslSocketFactoryBase(X509TrustManager trustManager, InputStream bksFile, String password, InputStream... certificates) {
SSLParams sslParams = new SSLParams();
try {
KeyManager[] keyManagers = prepareKeyManager(bksFile, password);
TrustManager[] trustManagers = prepareTrustManager(certificates);
X509TrustManager manager;
if (trustManager != null) {
//优先使用用户自定义的TrustManager
manager = trustManager;
} else if (trustManagers != null) {
//然后使用默认的TrustManager
manager = chooseTrustManager(trustManagers);
} else {
//否则使用不安全的TrustManager
manager = UnSafeTrustManager;
}
// 创建TLS类型的SSLContext对象, that uses our TrustManager
SSLContext sslContext = SSLContext.getInstance("TLS");
// 用上面得到的trustManagers初始化SSLContext,这样sslContext就会信任keyStore中的证书
// 第一个参数是授权的密钥管理器,用来授权验证,比如授权自签名的证书验证。第二个是被授权的证书管理器,用来验证服务器端的证书
sslContext.init(keyManagers, new TrustManager[]{manager}, null);
// 通过sslContext获取SSLSocketFactory对象
sslParams.sSLSocketFactory = sslContext.getSocketFactory();
sslParams.trustManager = manager;
return sslParams;
} catch (NoSuchAlgorithmException e) {
throw new AssertionError(e);
} catch (KeyManagementException e) {
throw new AssertionError(e);
}
}
private static KeyManager[] prepareKeyManager(InputStream bksFile, String password) {
try {
if (bksFile == null || password == null) return null;
KeyStore clientKeyStore = KeyStore.getInstance("BKS");
clientKeyStore.load(bksFile, password.toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(clientKeyStore, password.toCharArray());
return kmf.getKeyManagers();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static TrustManager[] prepareTrustManager(InputStream... certificates) {
if (certificates == null || certificates.length <= 0) return null;
try {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
// 创建一个默认类型的KeyStore,存储我们信任的证书
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
int index = 0;
for (InputStream certStream : certificates) {
String certificateAlias = Integer.toString(index++);
// 证书工厂根据证书文件的流生成证书 cert
Certificate cert = certificateFactory.generateCertificate(certStream);
// 将 cert 作为可信证书放入到keyStore中
keyStore.setCertificateEntry(certificateAlias, cert);
try {
if (certStream != null) certStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//我们创建一个默认类型的TrustManagerFactory
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
//用我们之前的keyStore实例初始化TrustManagerFactory,这样tmf就会信任keyStore中的证书
tmf.init(keyStore);
//通过tmf获取TrustManager数组,TrustManager也会信任keyStore中的证书
return tmf.getTrustManagers();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static X509TrustManager chooseTrustManager(TrustManager[] trustManagers) {
for (TrustManager trustManager : trustManagers) {
if (trustManager instanceof X509TrustManager) {
return (X509TrustManager) trustManager;
}
}
return null;
}
/**
* 为了解决客户端不信任服务器数字证书的问题,网络上大部分的解决方案都是让客户端不对证书做任何检查,
* 这是一种有很大安全漏洞的办法
*/
public static X509TrustManager UnSafeTrustManager = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
};
/**
* 此类是用于主机名验证的基接口。 在握手期间,如果 URL 的主机名和服务器的标识主机名不匹配,
* 则验证机制可以回调此接口的实现程序来确定是否应该允许此连接。策略可以是基于证书的或依赖于其他验证方案。
* 当验证 URL 主机名使用的默认规则失败时使用这些回调。如果主机名是可接受的,则返回 true
*/
public static HostnameVerifier UnSafeHostnameVerifier = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment