Commit bb841b64 authored by fengruiyu's avatar fengruiyu

Merge branch 'master' of http://39.97.65.143:81/android/android_street into fry_dev

 Conflicts:
	app/src/main/java/com/mints/street/login/LoginViewModel.kt
parents 3d65501d e937e0fc
......@@ -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')
......
......@@ -415,6 +415,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
......
......@@ -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