步骤1,在易班开放平台申请开发者账号,并创建轻应用
完成后可以在易班开放平台的管理中心可以看到:
步骤2,调用易班api获取用户的verify_request
GET请求访问https://openapi.yiban.cn/oauth/authorize?redirect_uri=${站内地址}&client_id=${APPID}&state=...
1。如果用户已登录且授权未过期,会自动重定向${应用地址}?verify_request=1e18f........&yb_uid=........&state=.....
。否则会在下列授权页面登录后再重定向。
步骤3,AES解密verify_request拿到access_token
易班官方的轻应用开发指南中提到的Java版本的AES封装库参考并不能直接适用于此需求,主要应该是没有偏移量或者向量。此处代码基本参考https://blog.csdn.net/wwwwww12432/article/details/107973996,但是并没有用到补丁包的任何文件。
...
import net.sf.json.JSONObject;
import java.util.Date;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AESTranferUtil {
// 默认的加密算法
private static final String CIPHER_ALGORITHM = "AES/CBC/NOPadding";
// 编码
private static final String ENCODING = "UTF-8";
// 算法
private static final String ALGORITHM = "AES";
/**
* 将hex格式转化成十进制
*/
public static byte[] hexToByte(String hex) {
int m = 0, n = 0;
int byteLen = hex.length() / 2; // 每两个字符描述一个字节
byte[] ret = new byte[byteLen];
for (int i = 0; i < byteLen; i++) {
m = i * 2 + 1;
n = m + 1;
int intVal = Integer.decode("0x" + hex.substring(i * 2, m) + hex.substring(m, n));
ret[i] = Byte.valueOf((byte) intVal);
}
return ret;
}
/**
* AES密文解析
*
* @param data 要解密的内容
* @param key 密码
* @param offset 偏移量
*/
public static String decrypt(String data, String key, String offset) throws Exception {
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("ASCII"), ALGORITHM);
IvParameterSpec iv = new IvParameterSpec(offset.getBytes());// 使用CBC模式,需要一个向量iv,可增加加密算法的强度
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] buffer = hexToByte(data);
byte[] encrypted = cipher.doFinal(buffer);
return new String(encrypted, ENCODING);// 此处使用BASE64做转码。
}
/**
* 将易班请求参数中的密文解析出用户信息
*
* @param data 要解密的内容
* @param key 密码 (appSecret)
* @param offset 偏移量 (appId)
* @return 关于返回值,如果返回的对象为空,说明是非法的密文,走正常登录; 如果对象的用户id登信息为空,未授权;不为空,已授权
*/
public static YiBanUserInfo jsonCode(String data, String key, String offset) {
try {
String plaintext = decrypt(data, key, offset);
System.out.println("plaintext:" + plaintext);
JSONObject plainJson = JSONObject.fromObject(plaintext.trim());
System.out.println("plainJson:" + plainJson);
Object visit_oauth = plainJson.get("visit_oauth");
System.out.println("visit_oauth:" + visit_oauth);
if (visit_oauth instanceof Boolean) {
if (false == (Boolean) visit_oauth) {
System.err.println("未授权");
return new YiBanUserInfo();
}
}
if (visit_oauth instanceof JSONObject) {
JSONObject oauthJson = (JSONObject) visit_oauth;
if (oauthJson.get("access_token") != null) {
System.err.println("已授权");
JSONObject visitUser = (JSONObject) plainJson.get("visit_user");
YiBanUserInfo yiBanUserInfo = new YiBanUserInfo();
yiBanUserInfo.setUserId(visitUser.getString("userid"));
yiBanUserInfo.setUserName(visitUser.getString("username"));
yiBanUserInfo.setUserNick(visitUser.getString("usernick"));
return yiBanUserInfo;
}
}
visit_oauth.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
String verify_request = "*********";
String appId = "*********";
String appKey = "*********";
YiBanUserInfo yiBanUserInfo = jsonCode(verify_request, appKey, appId);
System.out.println("yiBanUserInfo:" + yiBanUserInfo);
//Unix 时间戳是指从1970 年 1 月 1 日开始所经过的秒数:
System.out.println( new Date(1666681756*1000L) + " " + new Date(1666768156*1000L));
verify_request = "*********";
yiBanUserInfo = jsonCode(verify_request, appKey, appId);
System.out.println("yiBanUserInfo:" + yiBanUserInfo);
//看起来用户的access_token没有过期时,再走https://openapi.yiban.cn/oauth/authorize接口拿到的也只是已有的access_token.
System.out.println( new Date(1666682447*1000L) + " " + new Date(1666768156*1000L));
}
}