百度AI Access Token过期处理

时间:2024-03-30 11:07:11

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做了过期处理。

百度AI Access Token过期处理

 

Calendar.add方法参数:

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

 

百度AI Access Token过期处理

把日期提前一天,然后和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未过期,不需要重新获取");
		}

	}

}

 

打印结果

百度AI Access Token过期处理