1. 程式人生 > >Android移動端與伺服器api介面加密示例(AES,MD5,Token)

Android移動端與伺服器api介面加密示例(AES,MD5,Token)

移動端介面安全流程:

獲取token步驟:

    * 1.拿到從後臺返回的AES加密後的token

    * 2.根據約定祕鑰進行解密,並把token儲存下來

AES祕鑰由移動端和後臺商議決定

後臺驗證步驟:

    * 1.取出timestamp 驗證是否是過期請求,過期則不處理

    * 2.通過userId和token關係表查到token 用token替換sign

    * 3.對新生成的token進行MD5,和客戶端傳入的sign進行比較,一致則處理


Android程式碼示例:

Mainactivity

public class MainActivity extends AppCompatActivity {
    private TextView tvTokenKey;
    private TextView tvTokenAfter;
    private TextView tvUrlAfter;

    String token_test="Im token";
    String serect="Im Key";//此祕鑰必須和解密的時候祕鑰相同
    private String mTokenFromServer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tvTokenKey = (TextView) findViewById(R.id.tv_token_key);
        tvTokenAfter = (TextView) findViewById(R.id.tv_token_after);
        tvUrlAfter = (TextView) findViewById(R.id.tv_url_after);

    }


    //加密
    public void encrypt(View view) {
        //模擬服務端返回的token (加密之後的)
        mTokenFromServer = EncryptUtils.encrypt(token_test, serect);
        tvTokenKey.setText("密文:"+mTokenFromServer);
    }
    //解密
    public void decrypt(View view) {
        if (mTokenFromServer==null){
            Toast.makeText(this, "請先獲取密文", Toast.LENGTH_SHORT).show();
        }else{
        String token = ApiSecret.getToken(this,serect, mTokenFromServer);//真實token
        tvTokenAfter.setText("token:"+token);}
    }
    //獲取url
    public void getUrl(View view) {
        HashMap<String, String> map = new HashMap<>();
        map.put("userId","3");
        map.put("userName","2");
        String signUrl = ApiSecret.getSignUrl(this, "www.baidu.com", map); //模擬post上傳的資料
        tvUrlAfter.setText("url:"+signUrl);
    }
}


ApiSecret

package com.yorick.gyh.apisecret;

import android.content.Context;
import android.text.TextUtils;

import java.util.Map;
import java.util.Set;

/*************************************************************************************************
 * 作   者: 高永好
 * 完成日期:2017-07-03 15:17
 * 說明:對api進行加密處理
 ************************************************************************************************/

public class ApiSecret {

    /**
     * 獲取token步驟:
     * 1.拿到從後臺返回的AES加密後的token
     * 2.根據約定祕鑰進行解密,並把token儲存下來
     * 此方法用於:1,登入獲取token  2,token過期更新token
     * @param context
     * @param tokenFromServer AES加密後的
     */
    public static String getToken(Context context,String secret, String tokenFromServer){
        String token = EncryptUtils.decrypt(tokenFromServer, secret);
        //將token儲存下來,以便下次使用
        ACache.get(context).put("token",token);
        return token;
    }
    /**
     * 後臺驗證步驟:
     * 1.取出timestamp 驗證是否是過期請求,過期則不處理
     * 2.通過userId和token關係表查到token 用token替換sign
     * 3.對新生成的token進行MD5,和客戶端傳入的sign進行比較,一致則處理
     * @param url 請求的url
     * @param params 傳入的引數,需要包含userId,不包含token
     * @return
     */
        public static String getSignUrl(Context context,String url, Map<String,String> params){
            String token=ACache.get(context).getAsString("token");
            if (TextUtils.isEmpty(token)){
                try {
                    throw  new Exception("請先初始化token");
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return "";
            }
            long time = System.currentTimeMillis() /1000;
            String signUrl=url+"?";
            Set<String> keys = params.keySet();
            //構造正確的url
            for (String key:keys){
                signUrl+=key+"="+params.get(key)+"&";
            }
            //後臺對time進行判斷,比如兩個小時之後認為這是非法請求
            signUrl+=("timestamp="+time);
            //對www.baidu.com?userId=3×tamp=1231413&token=123456進行MD5編碼獲取到Sign
            String sign = EncryptUtils.encryptMD5ToString(signUrl+"&token="+token).toLowerCase();
            return signUrl+"&sign="+sign;
        }
}


EncryptUtils和Acache見demo    Demo :點此下載ApiSecret