1. 程式人生 > >百度AI Access Token過期處理

百度AI Access Token過期處理

Access Token作為請求百度AI介面以及太多需要第三方平臺開發介面的唯一憑據,都存在有效期的問題。而過期處理是很有必要的。

一、問題現狀

Access Token的獲取一般都是Https請求,涉及到跨域問題一般的解決辦法就是在後臺寫方法進行Http請求,將獲取到的結果傳遞到前臺頁面。

百度AI token請求的返回結果:

"access_token": "1.a6b7dbd428f731035f771b8d********.86400.1292922000-2346678-124328", "expires_in": 86400 

其中 expires_in 即為有效期 這裡一般是一個月。過期以後,再次使用就會報錯發現請求不成功。需要在使用到token的地方做過期判斷,過期重新獲取。

 

二、百度AI 官方介面問題

百度AI 介面的官方Demo中的很多介面都已經預設把token的獲取新增進去了,我這邊只是暫時用到了自然語言處理,jar包:(aip-java-sdk-4.4.1.jar)下載地址:(https://ai.baidu.com/sdk#nlp)發現AipNlp物件建立的時候,首先需要單例使用,避免多次重複建立token,其次最主要的是檢視原始碼發現已經對token做了過期處理。

 

Calendar.add方法引數:

如果是1則代表的是對年份操作,2是對月份操作,3是對星期操作,5是對日期操作,11是對小時操作,12是對分鐘操作,13是對秒操作,14是對毫秒操作。例如:Calendar calendar = Calendar.getInstance(); calendar .add(5,1);則表示對日期進行加一天操作
 

 

把日期提前一天,然後和token建立的時候一直到過期的時候的日期進行比較,after為true表示token過期。

 

 

三、解決辦法

1、獲取token的時候,伺服器會把token字串和有效期(expires_in )一起返回給您,token 預設有效期為一個月,您可以在獲取到Token後在伺服器做一個快取,或者直接寫入資料庫,在資料庫中建立token欄位和建立日期欄位。有效期驗證可以用當前時間戳減去獲取到token的時間戳與token有效期進行對比。

就是在用到token的時候做判斷:現在的時間-token建立的日期<30天 即未過期 過期以後重新請求token

2、主要參考官方jar包中的解決辦法。

aip-java-sdk-4.4.1.jar

官方demo涉及到多執行緒,多次請求token的時候需要判斷token是否已經獲取過,再判斷是否過期。

具體在專案中如何使用要看情況,還是多看下原始碼學習學習,確實寫的很嚴謹。


以下是我自己根據官方jar修改的,一個是判斷是否請求過,就是token是不是存在不為null,第二個是當多次請求的時候判斷token是否過期。

package com.baidu.ai;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import org.json.JSONObject;
/**
 * 獲取token類
 * 
 * token過期處理 2018.10.24 16:34 參考官方jar
 */
public class AuthService {

	/**
	 * 判斷token是否過期
	 */
	private static Calendar expireDate = null;
	private static boolean flag = false; // 是否已經獲取過了

	public static Boolean needAuth() {
		Calendar c = Calendar.getInstance();
		c.add(5, 1); // 當前日期加一天
		return Boolean.valueOf(!flag || c.after(expireDate));
	}

	/**
	 * 獲取許可權token
	 * 
	 * @return 返回示例: { "access_token":
	 *         "24.460da4889caad24cccdb1fea17221975.2592000.1491995545.282335-1234567",
	 *         "expires_in": 2592000 }
	 */
	public static String getAuth() {
		// 官網獲取的 API Key 更新為你註冊的
		String clientId = "你註冊的API Key";
		// 官網獲取的 Secret Key 更新為你註冊的
		String clientSecret = "你註冊的Secret Key";

		flag = true;

		return getAuth(clientId, clientSecret);
	}

	/**
	 * 獲取API訪問token 該token有一定的有效期,需要自行管理,當失效時需重新獲取.
	 * @param clientId  - 百度雲官網獲取的 API Key         
	 * @param clientSecret - 百度雲官網獲取的 Securet Key       
	 * @return assess_token   
	 */
	private static String getAuth(String clientId, String clientSecret) {
		// 獲取token地址
		String authHost = "https://aip.baidubce.com/oauth/2.0/token?";
		String getAccessTokenUrl = authHost
				// 1. grant_type為固定引數
				+ "grant_type=client_credentials"
				// 2. 官網獲取的 API Key
				+ "&client_id=" + clientId
				// 3. 官網獲取的 Secret Key
				+ "&client_secret=" + clientSecret;

		try {
			URL realUrl = new URL(getAccessTokenUrl);
			// 開啟和URL之間的連線
			HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
			connection.setRequestMethod("POST");
			connection.connect();

			// 獲取所有響應頭欄位
			Map<String, List<String>> map = connection.getHeaderFields();
			// 遍歷所有的響應頭欄位
			for (String key : map.keySet()) {
				System.err.println(key + "--->" + map.get(key));
			}
			// 定義 BufferedReader輸入流來讀取URL的響應
			BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
			String result = "";
			String line;
			while ((line = in.readLine()) != null) {
				result += line;
			}
			/**
			 * 返回結果示例
			 */
			System.err.println("result:" + result);
			JSONObject jsonObject = new JSONObject(result);
			String access_token = jsonObject.getString("access_token");

			Integer expires_in = Integer.valueOf(jsonObject.getInt("expires_in"));

			System.out.println("expires_in:" + expires_in);

			Calendar c = Calendar.getInstance();
			System.out.println("現在日期:" + c.get(c.YEAR) + "/" + c.get(c.MONTH) + "/" + c.get(c.DAY_OF_MONTH));
			c.add(13, expires_in.intValue());
			System.out.println("過期日期:" + c.get(c.YEAR) + "/" + c.get(c.MONTH) + "/" + c.get(c.DAY_OF_MONTH));
			expireDate = c;

			return access_token;

		} catch (Exception e) {
			System.err.printf("獲取token失敗!");
			e.printStackTrace(System.err);
		}
		return null;
	}

	public static void main(String[] args) {

		System.out.println("flag:" + flag);
		
		System.out.println("needAuth():" + needAuth().booleanValue());
		
		//第一次請求
		if (needAuth().booleanValue()) {
			String access_token = getAuth();
			
			System.out.println("flag:" + flag);
			
			System.out.println("access_token:" + access_token);
		} else {
			System.out.println("token未過期,不需要重新獲取");
		}
		
		//第二次請求
		if (needAuth().booleanValue()) {
			String access_token = getAuth();
			
			System.out.println("flag:" + flag);
			
			System.out.println("access_token:" + access_token);
		} else {
			System.out.println("token未過期,不需要重新獲取");
		}

	}

}

 

列印結果