最近需要使用微博开放平台的一些功能,由于官方sdk略坑,故决定自己写个HttpClient来模拟获取授权code。不多说,直接上代码。

首先配置微博开放平台基本参数。

private static String clientId = "你的clientId";
private static String redirectURI = "你的回调地址";
private static String url = "https://api.weibo.com/oauth2/authorize";
private static String userId = "你的账号";
private static String passwd = "你的密码";
private static String appkey = null;
private static HttpClient client = HttpClients.createDefault();
private static HttpResponse response = null;
private static HttpGet httpGet = null;
private static HttpEntity entity = null;
private static ScriptEngineManager sem = new ScriptEngineManager();
private static ScriptEngine se = sem.getEngineByName("javascript");
private static String getJS() {
return FileUtil.getString(PathKit.getRootClassPath() + File.separator + "sina.js", "UTF-8");
}
static {
try {
se.eval(getJS());
} catch (ScriptException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

然后获取需要授权的对应的Appkey,后面授权需要用到

/**
* 获取AppKey
*
* @return
*/
public static String getAppKey() {
httpGet = new HttpGet(url + "?withOfficalFlag=0&response_type=code&isLoginSina=0&redirect_uri=" + redirectURI
+ "&userId=" + userId + "&client_id=" + clientId);
httpGet.setHeader("Referer",
url + "?withOfficalFlag=0&passwd=" + passwd
+ "&action=submit&response_type=code&isLoginSina=0&redirect_uri=" + redirectURI + "&userId="
+ userId + "&client_id=" + clientId);
httpGet.setHeader("Host", "login.sina.com.cn");
httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; rv:11.0) Gecko/20100101 Firefox/11.0");
try {
response = client.execute(httpGet);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
if (response == null) {
return appkey;
}
entity = response.getEntity();
try {
// 执行回调函数
String preloginCallBack = EntityUtils.toString(entity);
int index = preloginCallBack.indexOf("http://app.weibo.com/t/feed/");
String temp = preloginCallBack.substring(index + 28, index + 34);
appkey = temp;
} catch (Exception e) {
// TODO: handle exception
}
return appkey;
}

然后获取加密后的用户名,登录的时候需要用到

   /**
* 获取加密后的用户名
*
* @return
*/
public static String getSu() {
Invocable inv = (Invocable) se;
try {
String su = (String) inv.invokeFunction("getUs", userId);
return su;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}

接着我们登录微博。

/**
* 登录, 传入加密的用户名
*
* @param su
* @return
*/
public static JSONObject login(String su) {
Invocable inv = (Invocable) se;
httpGet = new HttpGet(
"https://login.sina.com.cn/sso/prelogin.php?entry=openapi&callback=sinaSSOController.preloginCallBack&su="
+ su + "&rsakt=mod&checkpin=1&client=ssologin.js(v1.4.18)&_=" + System.currentTimeMillis());
httpGet.setHeader("Referer",
url + "?withOfficalFlag=0&passwd=" + passwd
+ "&action=submit&response_type=code&isLoginSina=0&redirect_uri=" + redirectURI + "&userId="
+ userId + "&client_id=" + clientId);
httpGet.setHeader("Host", "login.sina.com.cn");
httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; rv:11.0) Gecko/20100101 Firefox/11.0");
try {
response = client.execute(httpGet);
if (response != null) {
entity = response.getEntity();
// 执行回调函数
String preloginCallBack = EntityUtils.toString(entity);
se.eval(preloginCallBack);
// 执行自己加入的获取密码方法
String sp = (String) inv.invokeFunction("getPass", passwd);
preloginCallBack = preloginCallBack.replace("sinaSSOController.preloginCallBack(", "");
preloginCallBack = preloginCallBack.substring(0, preloginCallBack.length() - 1);
JSONObject obj = JSON.parseObject(preloginCallBack);
// 拼凑登陆数据
HttpPost loginPost = new HttpPost(
"https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.18)&_" + System.currentTimeMillis()
+ "&openapilogin=qrcode");
List<NameValuePair> formData = new ArrayList<>();
// 应用的App Key
formData.add(new BasicNameValuePair("entry", "openapi"));
// 应用的重定向页面
formData.add(new BasicNameValuePair("gateway", "1"));
// 模拟登录参数
// 开发者或测试账号的用户名和密码
formData.add(new BasicNameValuePair("from", ""));
formData.add(new BasicNameValuePair("savestate", "0"));
formData.add(new BasicNameValuePair("useticket", "1"));
formData.add(new BasicNameValuePair("pagerefer", url));
formData.add(new BasicNameValuePair("ct", "1800"));
formData.add(new BasicNameValuePair("s", "1"));
formData.add(new BasicNameValuePair("vsnf", "1"));
formData.add(new BasicNameValuePair("vsnval", ""));
formData.add(new BasicNameValuePair("door", ""));
formData.add(new BasicNameValuePair("appkey", appkey));
formData.add(new BasicNameValuePair("su", su));
formData.add(new BasicNameValuePair("service", "miniblog"));
formData.add(new BasicNameValuePair("servertime", obj.getString("servertime")));
formData.add(new BasicNameValuePair("nonce", obj.getString("nonce")));
formData.add(new BasicNameValuePair("pwencode", "rsa2"));
formData.add(new BasicNameValuePair("rsakv", obj.getString("rsakv")));
formData.add(new BasicNameValuePair("sp", sp));
formData.add(new BasicNameValuePair("sr", "1920*1080"));
formData.add(new BasicNameValuePair("encoding", "UTF-8"));
formData.add(new BasicNameValuePair("cdult", "2"));
formData.add(new BasicNameValuePair("domain", "weibo.com"));
formData.add(new BasicNameValuePair("prelt", "201"));
formData.add(new BasicNameValuePair("returntype", "TEXT"));
loginPost.setEntity(new UrlEncodedFormEntity(formData, Consts.UTF_8));
loginPost.setHeader("Referer",
url + "?withOfficalFlag=0&passwd=" + passwd
+ "&action=submit&response_type=code&isLoginSina=0&redirect_uri=" + redirectURI
+ "&userId=" + userId + "&client_id=" + clientId);
loginPost.setHeader("Host", "login.sina.com.cn");
loginPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; rv:11.0) Gecko/20100101 Firefox/11.0");
response = client.execute(loginPost);
if (response != null) {
entity = response.getEntity();
String loginSuccess = EntityUtils.toString(entity);
obj = JSON.parseObject(loginSuccess);
return obj;
}
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return null;
}

然后获取verifyToken。

/**
* 获取授权的token
*
* @param loginObj
* @return
*/
public static String getVerifyToken(JSONObject loginObj) {
// 授權登陸
HttpPost postMethod = new HttpPost(url);
List<NameValuePair> nvps = new ArrayList<>();
// 应用的App Key
nvps.add(new BasicNameValuePair("client_id", clientId));
// 应用的重定向页面
nvps.add(new BasicNameValuePair("redirect_uri", redirectURI));
// 模拟登录参数
// 开发者或测试账号的用户名和密码
nvps.add(new BasicNameValuePair("display", "default"));
// 猜測是登陸的權證
nvps.add(new BasicNameValuePair("ticket", loginObj.getString("ticket")));
// nvps.add(new BasicNameValuePair("uid",
// obj.getString("uid")));
nvps.add(new BasicNameValuePair("regCallback", url + "?client_id=" + clientId
+ "&response_type=code&display=default&redirect_uri=" + redirectURI + "&from=&with_cookie="));
nvps.add(new BasicNameValuePair("isLoginSina", "0"));
nvps.add(new BasicNameValuePair("action", "login"));
nvps.add(new BasicNameValuePair("withOfficalFlag", "0"));
nvps.add(new BasicNameValuePair("appkey62", appkey));
postMethod.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8));
// 添加头信息
postMethod.setHeader("Referer", url);
postMethod.setHeader("Host", "api.weibo.com");
postMethod.setHeader("Origin", "https://api.weibo.com");
postMethod.setHeader("Content-Type", "application/x-www-form-urlencoded");
postMethod.setHeader("Upgrade-Insecure-Requests", "1");
postMethod.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1;rv:11.0) Gecko/20100101 Firefox/11.0");
// client = HttpClients.createDefault();
response = null;
try {
response = client.execute(postMethod);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (response != null) {
entity = response.getEntity();
String verifyToken = null;
try {
String loginHtml = EntityUtils.toString(entity);
int index = loginHtml.indexOf("verifyToken") + 20;
String tmp = loginHtml.substring(index, loginHtml.length());
index = tmp.indexOf("/>");
tmp = tmp.substring(0, index - 1);
verifyToken = tmp;
return verifyToken;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}

最后我们就可以获取到获取token的code了

/**
*  获取授权code
* @param loginObj
* @param verifyToken
* @return
*/
public static String getCode(JSONObject loginObj, String verifyToken) {
// 正式授權
HttpPost postMethod = new HttpPost(url);
List<NameValuePair> nvps = new ArrayList<>();
nvps = new ArrayList<>();
// 应用的App Key
nvps.add(new BasicNameValuePair("client_id", clientId));
// 应用的重定向页面
nvps.add(new BasicNameValuePair("redirect_uri", redirectURI));
nvps.add(new BasicNameValuePair("display", "default"));
nvps.add(new BasicNameValuePair("uid", loginObj.getString("uid")));
nvps.add(new BasicNameValuePair("regCallback", url + "?client_id=" + clientId
+ "&response_type=code&display=default&redirect_uri=" + redirectURI + "&from=&with_cookie="));
nvps.add(new BasicNameValuePair("isLoginSina", "0"));
nvps.add(new BasicNameValuePair("action", "authorize"));
nvps.add(new BasicNameValuePair("withOfficalFlag", "0"));
nvps.add(new BasicNameValuePair("response_type", "code"));
nvps.add(new BasicNameValuePair("url", url));
nvps.add(new BasicNameValuePair("appkey62", appkey));
nvps.add(new BasicNameValuePair("verifyToken", verifyToken));
postMethod.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8));
// 添加头信息
postMethod.setHeader("Referer", url);
postMethod.setHeader("Host", "api.weibo.com");
postMethod.setHeader("Origin", "https://api.weibo.com");
postMethod.setHeader("Content-Type", "application/x-www-form-urlencoded");
postMethod.setHeader("Upgrade-Insecure-Requests", "1");
postMethod.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1;rv:11.0) Gecko/20100101 Firefox/11.0");
response = null;
try {
response = client.execute(postMethod);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (response != null) {
entity = response.getEntity();
try {
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Header location = response.getFirstHeader("Location");
if (location != null) {
String retUrl = location.getValue();
int begin = retUrl.indexOf("code=");
if (begin != -1) {
int end = retUrl.indexOf("&", begin);
if (end == -1)
end = retUrl.length();
String code = retUrl.substring(begin + 5, end);
return code;
}
}
}
return null;
}

获取code调用顺序。

       String appKey = SinaUtil.getAppKey();
System.out.println("appKey::::::::::::" + appKey);
String su = SinaUtil.getSu();
System.out.println("su::::::::::::" + su);
JSONObject obj = SinaUtil.login(su);
System.out.println("loginObj::::::::::::" + obj);
String verifyToken = SinaUtil.getVerifyToken(obj);
System.out.println("verifyToken::::::::::::" + verifyToken);
String code = SinaUtil.getCode(obj, verifyToken);
System.out.println("code::::::::::::" + code);

文中使用的代码,这个可能需要使用的时候进行修改,现在是可以使用。里面我加了两个方法,获取加密后用户名和密码。

var sinaSSOEncoder = sinaSSOEncoder || {};
(function () {
var k = 0;
var h = 8;
this.hex_sha1 = function (l) {
return i(c(g(l), l.length * h))
};
var c = function (B, s) {
B[s >> 5] |= 128 << (24 - s % 32);
B[((s + 64 >> 9) << 4) + 15] = s;
var C = Array(80);
var A = 1732584193;
var z = -271733879;
var y = -1732584194;
var v = 271733878;
var u = -1009589776;
for (var p = 0; p < B.length; p += 16) {
var r = A;
var q = z;
var o = y;
var n = v;
var l = u;
for (var m = 0; m < 80; m++) {
if (m < 16) {
C[m] = B[p + m]
} else {
C[m] = e(C[m - 3] ^ C[m - 8] ^ C[m - 14] ^ C[m - 16], 1)
}
var D = f(f(e(A, 5), a(m, z, y, v)), f(f(u, C[m]), d(m)));
u = v;
v = y;
y = e(z, 30);
z = A;
A = D
}
A = f(A, r);
z = f(z, q);
y = f(y, o);
v = f(v, n);
u = f(u, l)
}
return Array(A, z, y, v, u)
};
var a = function (m, l, o, n) {
if (m < 20) {
return (l & o) | ((~l) & n)
}
if (m < 40) {
return l ^ o ^ n
}
if (m < 60) {
return (l & o) | (l & n) | (o & n)
}
return l ^ o ^ n
};
var d = function (l) {
return (l < 20) ? 1518500249 : (l < 40) ? 1859775393 : (l < 60) ? -1894007588 : -899497514
};
var f = function (l, o) {
var n = (l & 65535) + (o & 65535);
var m = (l >> 16) + (o >> 16) + (n >> 16);
return (m << 16) | (n & 65535)
};
var e = function (l, m) {
return (l << m) | (l >>> (32 - m))
};
var g = function (o) {
var n = Array();
var l = (1 << h) - 1;
for (var m = 0; m < o.length * h; m += h) {
n[m >> 5] |= (o.charCodeAt(m / h) & l) << (24 - m % 32)
}
return n
};
var i = function (n) {
var m = k ? "0123456789ABCDEF" : "0123456789abcdef";
var o = "";
for (var l = 0; l < n.length * 4; l++) {
o += m.charAt((n[l >> 2] >> ((3 - l % 4) * 8 + 4)) & 15) + m.charAt((n[l >> 2] >> ((3 - l % 4) * 8)) & 15)
}
return o
};
var j = function (l) {
var m = "",
n = 0;
for (; n < l.length; n++) {
m += "%" + b(l[n])
}
return decodeURIComponent(m)
};
var b = function (l) {
var m = "0" + l.toString(16);
return m.length <= 2 ? m : m.substr(1)
};
this.base64 = {
encode: function (n) {
n = "" + n;
if (n == "") {
return ""
}
var l = "";
var u, s, q = "";
var t, r, p, o = "";
var m = 0;
do {
u = n.charCodeAt(m++);
s = n.charCodeAt(m++);
q = n.charCodeAt(m++);
t = u >> 2;
r = ((u & 3) << 4) | (s >> 4);
p = ((s & 15) << 2) | (q >> 6);
o = q & 63;
if (isNaN(s)) {
p = o = 64
} else {
if (isNaN(q)) {
o = 64
}
}
l = l + this._1.charAt(t) + this._1.charAt(r) + this._1.charAt(p) + this._1.charAt(o);
u = s = q = "";
t = r = p = o = ""
} while (m < n.length);
return l
},
decode: function (t, q, m) {
var s = function (C, E) {
for (var D = 0; D < C.length; D++) {
if (C[D] === E) {
return D
}
}
return -1
};
if (typeof(t) == "string") {
t = t.split("")
}
var n = [];
var B, z, w = "";
var A, y, v, u = "";
if (t.length % 4 != 0) {}
var l = /[^A-Za-z0-9+\/=]/;
var x = this._1.split("");
if (q == "urlsafe") {
l = /[^A-Za-z0-9-_=]/;
x = this._4.split("")
}
if (q == "subp_v2") {
l = /[^A-Za-z0-9_=-]/;
x = this._3.split("")
}
if (q == "subp_v3_3") {
l = /[^A-Za-z0-9-_.-]/;
x = this._2.split("")
}
var p = 0;
if (q == "binnary") {
x = [];
for (p = 0; p <= 64; p++) {
x[p] = p + 128
}
}
if (q != "binnary" && l.test(t.join(""))) {
return m == "array" ? [] : ""
}
p = 0;
do {
A = s(x, t[p++]);
y = s(x, t[p++]);
v = s(x, t[p++]);
u = s(x, t[p++]);
B = (A << 2) | (y >> 4);
z = ((y & 15) << 4) | (v >> 2);
w = ((v & 3) << 6) | u;
n.push(B);
if (v != 64 && v != -1) {
n.push(z)
}
if (u != 64 && u != -1) {
n.push(w)
}
B = z = w = "";
A = y = v = u = ""
} while (p < t.length);
if (m == "array") {
return n
}
var r = "",
o = 0;
for (; o < n.lenth; o++) {
r += String.fromCharCode(n[o])
}
return r
},
_1: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
_4: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=",
_3: "uAL715W8e3jJCcNU0lT_FSXVgxpbEDdQ4vKaIOH2GBPtfzqsmYZo-wRM9i6hynrk=",
_2: "5WFh28sGziZTeS1lBxCK-HgPq9IdMUwknybo.LJrQD3uj_Va7pE0XfcNR4AOYvm6t"
};
this.Cookie = {
decode: function (o) {
var n = [];
var m = o.substr(0, 3);
var l = o.substr(3);
switch (m) {
case "v01":
for (var p = 0; p < l.length; p += 2) {
n.push(parseInt(l.substr(p, 2), 16))
}
return decodeURIComponent(j(sinaSSOEncoder.base64.decode(n, "binnary", "array")));
break;
case "v02":
l = l.replace(/\./g, "=");
n = sinaSSOEncoder.base64.decode(l, "urlsafe", "array");
return j(sinaSSOEncoder.base64.decode(n, "binnary", "array"));
default:
return decodeURIComponent(o)
}
}
};
this.getSUBPCookie = {
__parse: function (o) {
var y, m, p, n, x, r = 0,
q, t = {},
l = "",
u = "";
if (!o) {
return t
}
do {
m = o[r];
y = ++r;
for (q = r; q < m + y; q++, r++) {
l += String.fromCharCode(o[q])
}
n = o[r];
y = ++r;
if (l == "status" || l == "flag") {
for (q = r; q < n + y; q++, r++) {
u += o[q]
}
} else {
u = o.slice(y, n + y);
try {
u = j(u)
} catch (w) {
u = ""
}
r += n
}
t[l] = u;
l = "";
u = ""
} while (r < o.length);
return t
},
decode: function (o) {
var n = [],
p, m = o.substr(0, 3),
l = decodeURIComponent(o.substr(3));
switch (m) {
case "002":
n = sinaSSOEncoder.base64.decode(l, "subp_v2", "array");
return sinaSSOEncoder.getSUBPCookie.__parse(n);
case "003":
p = l.substr(0, 1);
l = l.substr(1);
n = sinaSSOEncoder.base64.decode(l, "subp_v3_" + p, "array");
return sinaSSOEncoder.getSUBPCookie.__parse(n);
default:
return decodeURIComponent(o)
}
}
}
}).call(sinaSSOEncoder);
(function () {
var av;
var ah = 244837814094590;
var Y = ((ah & 16777215) == 15715070);
function aq(z, t, az) {
if (z != null) {
if ("number" == typeof z) {
this.fromNumber(z, t, az)
} else {
if (t == null && "string" != typeof z) {
this.fromString(z, 256)
} else {
this.fromString(z, t)
}
}
}
}
function h() {
return new aq(null)
}
function b(aB, t, z, aA, aD, aC) {
while (--aC >= 0) {
var az = t * this[aB++] + z[aA] + aD;
aD = Math.floor(az / 67108864);
z[aA++] = az & 67108863
}
return aD
}
function ax(aB, aG, aH, aA, aE, t) {
var aD = aG & 32767,
aF = aG >> 15;
while (--t >= 0) {
var az = this[aB] & 32767;
var aC = this[aB++] >> 15;
var z = aF * az + aC * aD;
az = aD * az + ((z & 32767) << 15) + aH[aA] + (aE & 1073741823);
aE = (az >>> 30) + (z >>> 15) + aF * aC + (aE >>> 30);
aH[aA++] = az & 1073741823
}
return aE
}
function aw(aB, aG, aH, aA, aE, t) {
var aD = aG & 16383,
aF = aG >> 14;
while (--t >= 0) {
var az = this[aB] & 16383;
var aC = this[aB++] >> 14;
var z = aF * az + aC * aD;
az = aD * az + ((z & 16383) << 14) + aH[aA] + aE;
aE = (az >> 28) + (z >> 14) + aF * aC;
aH[aA++] = az & 268435455
}
return aE
}
// if (Y && (navigator.appName == "Microsoft Internet Explorer")) {
// aq.prototype.am = ax;
// av = 30
// } else {
// if (Y && (navigator.appName != "Netscape")) {
aq.prototype.am = b;
av = 26
// } else {
// aq.prototype.am = aw;
// av = 28
// }
// }
aq.prototype.DB = av;
aq.prototype.DM = ((1 << av) - 1);
aq.prototype.DV = (1 << av);
var Z = 52;
aq.prototype.FV = Math.pow(2, Z);
aq.prototype.F1 = Z - av;
aq.prototype.F2 = 2 * av - Z;
var ad = "0123456789abcdefghijklmnopqrstuvwxyz";
var af = new Array();
var ao, v;
ao = "0".charCodeAt(0);
for (v = 0; v <= 9; ++v) {
af[ao++] = v
}
ao = "a".charCodeAt(0);
for (v = 10; v < 36; ++v) {
af[ao++] = v
}
ao = "A".charCodeAt(0);
for (v = 10; v < 36; ++v) {
af[ao++] = v
}
function ay(t) {
return ad.charAt(t)
}
function A(z, t) {
var az = af[z.charCodeAt(t)];
return (az == null) ? -1 : az
}
function X(z) {
for (var t = this.t - 1; t >= 0; --t) {
z[t] = this[t]
}
z.t = this.t;
z.s = this.s
}
function n(t) {
this.t = 1;
this.s = (t < 0) ? -1 : 0;
if (t > 0) {
this[0] = t
} else {
if (t < -1) {
this[0] = t + DV
} else {
this.t = 0
}
}
}
function c(t) {
var z = h();
z.fromInt(t);
return z
}
function w(aD, z) {
var aA;
if (z == 16) {
aA = 4
} else {
if (z == 8) {
aA = 3
} else {
if (z == 256) {
aA = 8
} else {
if (z == 2) {
aA = 1
} else {
if (z == 32) {
aA = 5
} else {
if (z == 4) {
aA = 2
} else {
this.fromRadix(aD, z);
return
}
}
}
}
}
}
this.t = 0;
this.s = 0;
var aC = aD.length,
az = false,
aB = 0;
while (--aC >= 0) {
var t = (aA == 8) ? aD[aC] & 255 : A(aD, aC);
if (t < 0) {
if (aD.charAt(aC) == "-") {
az = true
}
continue
}
az = false;
if (aB == 0) {
this[this.t++] = t
} else {
if (aB + aA > this.DB) {
this[this.t - 1] |= (t & ((1 << (this.DB - aB)) - 1)) << aB;
this[this.t++] = (t >> (this.DB - aB))
} else {
this[this.t - 1] |= t << aB
}
}
aB += aA;
if (aB >= this.DB) {
aB -= this.DB
}
}
if (aA == 8 && (aD[0] & 128) != 0) {
this.s = -1;
if (aB > 0) {
this[this.t - 1] |= ((1 << (this.DB - aB)) - 1) << aB
}
}
this.clamp();
if (az) {
aq.ZERO.subTo(this, this)
}
}
function O() {
var t = this.s & this.DM;
while (this.t > 0 && this[this.t - 1] == t) {
--this.t
}
}
function q(z) {
if (this.s < 0) {
return "-" + this.negate().toString(z)
}
var az;
if (z == 16) {
az = 4
} else {
if (z == 8) {
az = 3
} else {
if (z == 2) {
az = 1
} else {
if (z == 32) {
az = 5
} else {
if (z == 4) {
az = 2
} else {
return this.toRadix(z)
}
}
}
}
}
var aB = (1 << az) - 1,
aE, t = false,
aC = "",
aA = this.t;
var aD = this.DB - (aA * this.DB) % az;
if (aA-- > 0) {
if (aD < this.DB && (aE = this[aA] >> aD) > 0) {
t = true;
aC = ay(aE)
}
while (aA >= 0) {
if (aD < az) {
aE = (this[aA] & ((1 << aD) - 1)) << (az - aD);
aE |= this[--aA] >> (aD += this.DB - az)
} else {
aE = (this[aA] >> (aD -= az)) & aB;
if (aD <= 0) {
aD += this.DB;
--aA
}
}
if (aE > 0) {
t = true
}
if (t) {
aC += ay(aE)
}
}
}
return t ? aC : "0"
}
function R() {
var t = h();
aq.ZERO.subTo(this, t);
return t
}
function ak() {
return (this.s < 0) ? this.negate() : this
}
function G(t) {
var az = this.s - t.s;
if (az != 0) {
return az
}
var z = this.t;
az = z - t.t;
if (az != 0) {
return az
}
while (--z >= 0) {
if ((az = this[z] - t[z]) != 0) {
return az
}
}
return 0
}
function j(z) {
var aA = 1,
az;
if ((az = z >>> 16) != 0) {
z = az;
aA += 16
}
if ((az = z >> 8) != 0) {
z = az;
aA += 8
}
if ((az = z >> 4) != 0) {
z = az;
aA += 4
}
if ((az = z >> 2) != 0) {
z = az;
aA += 2
}
if ((az = z >> 1) != 0) {
z = az;
aA += 1
}
return aA
}
function u() {
if (this.t <= 0) {
return 0
}
return this.DB * (this.t - 1) + j(this[this.t - 1] ^ (this.s & this.DM))
}
function ap(az, z) {
var t;
for (t = this.t - 1; t >= 0; --t) {
z[t + az] = this[t]
}
for (t = az - 1; t >= 0; --t) {
z[t] = 0
}
z.t = this.t + az;
z.s = this.s
}
function W(az, z) {
for (var t = az; t < this.t; ++t) {
z[t - az] = this[t]
}
z.t = Math.max(this.t - az, 0);
z.s = this.s
}
function s(aE, aA) {
var z = aE % this.DB;
var t = this.DB - z;
var aC = (1 << t) - 1;
var aB = Math.floor(aE / this.DB),
aD = (this.s << z) & this.DM,
az;
for (az = this.t - 1; az >= 0; --az) {
aA[az + aB + 1] = (this[az] >> t) | aD;
aD = (this[az] & aC) << z
}
for (az = aB - 1; az >= 0; --az) {
aA[az] = 0
}
aA[aB] = aD;
aA.t = this.t + aB + 1;
aA.s = this.s;
aA.clamp()
}
function l(aD, aA) {
aA.s = this.s;
var aB = Math.floor(aD / this.DB);
if (aB >= this.t) {
aA.t = 0;
return
}
var z = aD % this.DB;
var t = this.DB - z;
var aC = (1 << z) - 1;
aA[0] = this[aB] >> z;
for (var az = aB + 1; az < this.t; ++az) {
aA[az - aB - 1] |= (this[az] & aC) << t;
aA[az - aB] = this[az] >> z
}
if (z > 0) {
aA[this.t - aB - 1] |= (this.s & aC) << t
}
aA.t = this.t - aB;
aA.clamp()
}
function aa(z, aA) {
var az = 0,
aB = 0,
t = Math.min(z.t, this.t);
while (az < t) {
aB += this[az] - z[az];
aA[az++] = aB & this.DM;
aB >>= this.DB
}
if (z.t < this.t) {
aB -= z.s;
while (az < this.t) {
aB += this[az];
aA[az++] = aB & this.DM;
aB >>= this.DB
}
aB += this.s
} else {
aB += this.s;
while (az < z.t) {
aB -= z[az];
aA[az++] = aB & this.DM;
aB >>= this.DB
}
aB -= z.s
}
aA.s = (aB < 0) ? -1 : 0;
if (aB < -1) {
aA[az++] = this.DV + aB
} else {
if (aB > 0) {
aA[az++] = aB
}
}
aA.t = az;
aA.clamp()
}
function D(z, aA) {
var t = this.abs(),
aB = z.abs();
var az = t.t;
aA.t = az + aB.t;
while (--az >= 0) {
aA[az] = 0
}
for (az = 0; az < aB.t; ++az) {
aA[az + t.t] = t.am(0, aB[az], aA, az, 0, t.t)
}
aA.s = 0;
aA.clamp();
if (this.s != z.s) {
aq.ZERO.subTo(aA, aA)
}
}
function Q(az) {
var t = this.abs();
var z = az.t = 2 * t.t;
while (--z >= 0) {
az[z] = 0
}
for (z = 0; z < t.t - 1; ++z) {
var aA = t.am(z, t[z], az, 2 * z, 0, 1);
if ((az[z + t.t] += t.am(z + 1, 2 * t[z], az, 2 * z + 1, aA, t.t - z - 1)) >= t.DV) {
az[z + t.t] -= t.DV;
az[z + t.t + 1] = 1
}
}
if (az.t > 0) {
az[az.t - 1] += t.am(z, t[z], az, 2 * z, 0, 1)
}
az.s = 0;
az.clamp()
}
function E(aH, aE, aD) {
var aN = aH.abs();
if (aN.t <= 0) {
return
}
var aF = this.abs();
if (aF.t < aN.t) {
if (aE != null) {
aE.fromInt(0)
}
if (aD != null) {
this.copyTo(aD)
}
return
}
if (aD == null) {
aD = h()
}
var aB = h(),
z = this.s,
aG = aH.s;
var aM = this.DB - j(aN[aN.t - 1]);
if (aM > 0) {
aN.lShiftTo(aM, aB);
aF.lShiftTo(aM, aD)
} else {
aN.copyTo(aB);
aF.copyTo(aD)
}
var aJ = aB.t;
var az = aB[aJ - 1];
if (az == 0) {
return
}
var aI = az * (1 << this.F1) + ((aJ > 1) ? aB[aJ - 2] >> this.F2 : 0);
var aQ = this.FV / aI,
aP = (1 << this.F1) / aI,
aO = 1 << this.F2;
var aL = aD.t,
aK = aL - aJ,
aC = (aE == null) ? h() : aE;
aB.dlShiftTo(aK, aC);
if (aD.compareTo(aC) >= 0) {
aD[aD.t++] = 1;
aD.subTo(aC, aD)
}
aq.ONE.dlShiftTo(aJ, aC);
aC.subTo(aB, aB);
while (aB.t < aJ) {
aB[aB.t++] = 0
}
while (--aK >= 0) {
var aA = (aD[--aL] == az) ? this.DM : Math.floor(aD[aL] * aQ + (aD[aL - 1] + aO) * aP);
if ((aD[aL] += aB.am(0, aA, aD, aK, 0, aJ)) < aA) {
aB.dlShiftTo(aK, aC);
aD.subTo(aC, aD);
while (aD[aL] < --aA) {
aD.subTo(aC, aD)
}
}
}
if (aE != null) {
aD.drShiftTo(aJ, aE);
if (z != aG) {
aq.ZERO.subTo(aE, aE)
}
}
aD.t = aJ;
aD.clamp();
if (aM > 0) {
aD.rShiftTo(aM, aD)
}
if (z < 0) {
aq.ZERO.subTo(aD, aD)
}
}
function N(t) {
var z = h();
this.abs().divRemTo(t, null, z);
if (this.s < 0 && z.compareTo(aq.ZERO) > 0) {
t.subTo(z, z)
}
return z
}
function K(t) {
this.m = t
}
function U(t) {
if (t.s < 0 || t.compareTo(this.m) >= 0) {
return t.mod(this.m)
} else {
return t
}
}
function aj(t) {
return t
}
function J(t) {
t.divRemTo(this.m, null, t)
}
function H(t, az, z) {
t.multiplyTo(az, z);
this.reduce(z)
}
function at(t, z) {
t.squareTo(z);
this.reduce(z)
}
K.prototype.convert = U;
K.prototype.revert = aj;
K.prototype.reduce = J;
K.prototype.mulTo = H;
K.prototype.sqrTo = at;
function B() {
if (this.t < 1) {
return 0
}
var t = this[0];
if ((t & 1) == 0) {
return 0
}
var z = t & 3;
z = (z * (2 - (t & 15) * z)) & 15;
z = (z * (2 - (t & 255) * z)) & 255;
z = (z * (2 - (((t & 65535) * z) & 65535))) & 65535;
z = (z * (2 - t * z % this.DV)) % this.DV;
return (z > 0) ? this.DV - z : -z
}
function f(t) {
this.m = t;
this.mp = t.invDigit();
this.mpl = this.mp & 32767;
this.mph = this.mp >> 15;
this.um = (1 << (t.DB - 15)) - 1;
this.mt2 = 2 * t.t
}
function ai(t) {
var z = h();
t.abs().dlShiftTo(this.m.t, z);
z.divRemTo(this.m, null, z);
if (t.s < 0 && z.compareTo(aq.ZERO) > 0) {
this.m.subTo(z, z)
}
return z
}
function ar(t) {
var z = h();
t.copyTo(z);
this.reduce(z);
return z
}
function P(t) {
while (t.t <= this.mt2) {
t[t.t++] = 0
}
for (var az = 0; az < this.m.t; ++az) {
var z = t[az] & 32767;
var aA = (z * this.mpl + (((z * this.mph + (t[az] >> 15) * this.mpl) & this.um) << 15)) & t.DM;
z = az + this.m.t;
t[z] += this.m.am(0, aA, t, az, 0, this.m.t);
while (t[z] >= t.DV) {
t[z] -= t.DV;
t[++z]++
}
}
t.clamp();
t.drShiftTo(this.m.t, t);
if (t.compareTo(this.m) >= 0) {
t.subTo(this.m, t)
}
}
function al(t, z) {
t.squareTo(z);
this.reduce(z)
}
function y(t, az, z) {
t.multiplyTo(az, z);
this.reduce(z)
}
f.prototype.convert = ai;
f.prototype.revert = ar;
f.prototype.reduce = P;
f.prototype.mulTo = y;
f.prototype.sqrTo = al;
function i() {
return ((this.t > 0) ? (this[0] & 1) : this.s) == 0
}
function x(aE, aF) {
if (aE > 4294967295 || aE < 1) {
return aq.ONE
}
var aD = h(),
az = h(),
aC = aF.convert(this),
aB = j(aE) - 1;
aC.copyTo(aD);
while (--aB >= 0) {
aF.sqrTo(aD, az);
if ((aE & (1 << aB)) > 0) {
aF.mulTo(az, aC, aD)
} else {
var aA = aD;
aD = az;
az = aA
}
}
return aF.revert(aD)
}
function am(az, t) {
var aA;
if (az < 256 || t.isEven()) {
aA = new K(t)
} else {
aA = new f(t)
}
return this.exp(az, aA)
}
aq.prototype.copyTo = X;
aq.prototype.fromInt = n;
aq.prototype.fromString = w;
aq.prototype.clamp = O;
aq.prototype.dlShiftTo = ap;
aq.prototype.drShiftTo = W;
aq.prototype.lShiftTo = s;
aq.prototype.rShiftTo = l;
aq.prototype.subTo = aa;
aq.prototype.multiplyTo = D;
aq.prototype.squareTo = Q;
aq.prototype.divRemTo = E;
aq.prototype.invDigit = B;
aq.prototype.isEven = i;
aq.prototype.exp = x;
aq.prototype.toString = q;
aq.prototype.negate = R;
aq.prototype.abs = ak;
aq.prototype.compareTo = G;
aq.prototype.bitLength = u;
aq.prototype.mod = N;
aq.prototype.modPowInt = am;
aq.ZERO = c(0);
aq.ONE = c(1);
function k() {
this.i = 0;
this.j = 0;
this.S = new Array()
}
function e(aB) {
var aA, z, az;
for (aA = 0; aA < 256; ++aA) {
this.S[aA] = aA
}
z = 0;
for (aA = 0; aA < 256; ++aA) {
z = (z + this.S[aA] + aB[aA % aB.length]) & 255;
az = this.S[aA];
this.S[aA] = this.S[z];
this.S[z] = az
}
this.i = 0;
this.j = 0
}
function a() {
var z;
this.i = (this.i + 1) & 255;
this.j = (this.j + this.S[this.i]) & 255;
z = this.S[this.i];
this.S[this.i] = this.S[this.j];
this.S[this.j] = z;
return this.S[(z + this.S[this.i]) & 255]
}
k.prototype.init = e;
k.prototype.next = a;
function an() {
return new k()
}
var M = 256;
var m;
var T;
var ab;
function d(t) {
T[ab++] ^= t & 255;
T[ab++] ^= (t >> 8) & 255;
T[ab++] ^= (t >> 16) & 255;
T[ab++] ^= (t >> 24) & 255;
if (ab >= M) {
ab -= M
}
}
function S() {
d(new Date().getTime())
}
if (T == null) {
T = new Array();
ab = 0;
var I;
// if (navigator.appName == "Netscape" && navigator.appVersion < "5" &&
// window.crypto && typeof(window.crypto.random) === "function") {
// var F = window.crypto.random(32);
// for (I = 0; I < F.length; ++I) {
// T[ab++] = F.charCodeAt(I) & 255
// }
// }
while (ab < M) {
I = Math.floor(65536 * Math.random());
T[ab++] = I >>> 8;
T[ab++] = I & 255
}
ab = 0;
S()
}
function C() {
if (m == null) {
S();
m = an();
m.init(T);
for (ab = 0; ab < T.length; ++ab) {
T[ab] = 0
}
ab = 0
}
return m.next()
}
function au(z) {
var t;
for (t = 0; t < z.length; ++t) {
z[t] = C()
}
}
function ac() {}
ac.prototype.nextBytes = au;
function g(z, t) {
return new aq(z, t)
}
function ag(az, aA) {
var t = "";
var z = 0;
while (z + aA < az.length) {
t += az.substring(z, z + aA) + "\n";
z += aA
}
return t + az.substring(z, az.length)
}
function r(t) {
if (t < 16) {
return "0" + t.toString(16)
} else {
return t.toString(16)
}
}
function ae(aA, aD) {
if (aD < aA.length + 11) {
alert("Message too long for RSA");
return null
}
var aC = new Array();
var az = aA.length - 1;
while (az >= 0 && aD > 0) {
var aB = aA.charCodeAt(az--);
if (aB < 128) {
aC[--aD] = aB
} else {
if ((aB > 127) && (aB < 2048)) {
aC[--aD] = (aB & 63) | 128;
aC[--aD] = (aB >> 6) | 192
} else {
aC[--aD] = (aB & 63) | 128;
aC[--aD] = ((aB >> 6) & 63) | 128;
aC[--aD] = (aB >> 12) | 224
}
}
}
aC[--aD] = 0;
var z = new ac();
var t = new Array();
while (aD > 2) {
t[0] = 0;
while (t[0] == 0) {
z.nextBytes(t)
}
aC[--aD] = t[0]
}
aC[--aD] = 2;
aC[--aD] = 0;
return new aq(aC)
}
function L() {
this.n = null;
this.e = 0;
this.d = null;
this.p = null;
this.q = null;
this.dmp1 = null;
this.dmq1 = null;
this.coeff = null
}
function o(z, t) {
if (z != null && t != null && z.length > 0 && t.length > 0) {
this.n = g(z, 16);
this.e = parseInt(t, 16)
} else {
alert("Invalid RSA public key")
}
}
function V(t) {
return t.modPowInt(this.e, this.n)
}
function p(az) {
var t = ae(az, (this.n.bitLength() + 7) >> 3);
if (t == null) {
return null
}
var aA = this.doPublic(t);
if (aA == null) {
return null
}
var z = aA.toString(16);
if ((z.length & 1) == 0) {
return z
} else {
return "0" + z
}
}
L.prototype.doPublic = V;
L.prototype.setPublic = o;
L.prototype.encrypt = p;
this.RSAKey = L
}).call(sinaSSOEncoder);
function SSOController() {
var undefined;
var me = this;
var updateCookieTimer = null;
var updateCookieTimeHardLimit = 1800;
var cookieExpireTimeLength = 3600 * 24;
var crossDomainForward = null;
var crossDomainTimer = null;
var crossDomainTime = 3;
var autoLoginCallBack2 = null;
var ssoCrosssDomainUrl = "http://login.sina.com.cn/sso/crossdomain.php";
var ssoLoginUrl = "http://login.sina.com.cn/sso/login.php";
var ssoLogoutUrl = "http://login.sina.com.cn/sso/logout.php";
var ssoUpdateCookieUrl = "http://login.sina.com.cn/sso/updatetgt.php";
var ssoPreLoginUrl = "http://login.sina.com.cn/sso/prelogin.php";
var pincodeUrl = "http://login.sina.com.cn/cgi/pin.php";
var vfValidUrl = "http://weibo.com/sguide/vdun.php";
var generateVisitorUrl = "http://passport.weibo.com/visitor/visitor";
var crossDomainUrlList = null;
var loginMethod = "";
var ssoServerTimeTimer = null;
var ssoLoginTimer = null;
var loginByConfig = null;
var loginMethodCheck = null;
var https = 1;
var rsa = 2;
var wsse = 4;
var pcid = "";
var tmpData = {};
var preloginTimeStart = 0;
var preloginTime = 0;
var callbackLogoutStatus;
this.https = 1;
this.rsa = 2;
this.wsse = 4;
this.name = "sinaSSOController";
this.loginFormId = "ssoLoginForm";
this.scriptId = "ssoLoginScript";
this.ssoCrossDomainScriptId = "ssoCrossDomainScriptId";
this.loginFrameName = "ssoLoginFrame";
this.appLoginURL = {
"weibo.com": "https://passport.weibo.com/wbsso/login"
};
this.appDomainService = {
"weibo.com": "miniblog"
};
this.loginExtraQuery = {};
this.setDomain = false;
this.feedBackUrl = "";
this.service = "sso";
this.domain = "sina.com.cn";
this.from = "";
this.pageCharset = "GB2312";
this.useTicket = false;
this.isCheckLoginState = false;
this.isUpdateCookieOnLoad = true;
this.useIframe = true;
this.noActiveTime = 7200;
this.autoUpdateCookieTime = 1800;
this.loginType = rsa;
this.timeoutEnable = false;
this.loginTimeout = 5000;
this.crossDomain = true;
this.scriptLoginHttps = false;
this.allowAutoFoundServerTime = false;
this.allowAutoFoundServerTimeError = true;
this.calcServerTimeInterval = 2000;
this.servertime = null;
this.nonce = null;
this.rsaPubkey = null;
this.rsakv = null;
this.loginExtraFlag = {};
this.cdult = false;
this.crossDomainTime = 5;
this.failRedirect = false;
this.isGenerateVisitor = true;
this.generateVisitorProbability = 1;
this.generateVisitorDelay = 6;
this.generateVisitorDomain = ["^.*sina.com.cn$"];
this.getVersion = function () {
return "ssologin.js(v1.4.18) 2014-06-12"
};
this.getEntry = function () {
return me.entry
};
this.getClientType = function () {
return me.getVersion().split(" ")[0]
};
this.customInit = function () {};
this.customUpdateCookieCallBack = function (result) {};
this.customLoginCallBack = function (loginStatus) {};
this.customLogoutCallBack = function (result) {
me.customLoginCallBack({
result: false
})
};
this.preloginCallBack = function (result) {
if (result && result.retcode == 0) {
me.servertime = result.servertime;
me.nonce = result.nonce;
me.rsaPubkey = result.pubkey;
me.rsakv = result.rsakv;
pcid = result.pcid;
preloginTime = (new Date()).getTime() - (new Date()).getTime() - (parseInt(result.exectime, 10) || 0)
}
}
var parse_str = function (str) {
var arr = str.split("&");
var arrtmp;
var arrResult = {};
for (var i = 0; i < arr.length; i++) {
arrtmp = arr[i].split("=");
arrResult[arrtmp[0]] = urldecode(arrtmp[1])
}
return arrResult
};
}
sinaSSOController = new SSOController();
function getUs(username){
return sinaSSOEncoder.base64.encode(username);
}
function getPass(password){
var RSAKey = new sinaSSOEncoder.RSAKey();
RSAKey.setPublic(sinaSSOController.rsaPubkey, '10001');
password = RSAKey.encrypt([sinaSSOController.servertime, sinaSSOController.nonce].join('\t') + '\n' + password);
return password
}

使用HttpClient登录微博开放平台,获取授权code相关推荐

  1. 【49.Auth2.0认证与授权过程-微博开放平台认证授权过程-百度开放平台认证授权过程-社交登录实现(微博授权)-分布式Session问题与解决方案-SpringSession整合-Redis】

    一.知识回顾 [0.三高商城系统的专题专栏都帮你整理好了,请点击这里!] [1-系统架构演进过程] [2-微服务系统架构需求] [3-高性能.高并发.高可用的三高商城系统项目介绍] [4-Linux云 ...

  2. 网站接入微博快捷登录-微博开放平台

    微博开放平台地址 因为我是接入web网站微博登录功能,所以,跳过移动应用部分,向下滑动 Web网站 OAuth2.0授权,与微博登录组件. 示例 使用接口深度开发,适合后端开发人员 使用微博的OAut ...

  3. java Oauth2微博开放平台登录授权接入

    --前期准备 微博开放平台登录账号,地址:https://open.weibo.com/ 提交身份认证(个人真实姓名.身份证号.身份证照片)审核需要3天左右 注册应用 填写应用名(选择网页应用) 注册 ...

  4. 腾讯微博开放平台授权教程(1)

    看到坛子里众多开发者问了很多授权问题,官方又没有及时解答,主要是他的API文档有些细节不够明确,经过几天的摸索,我将摸索到的经验以图文及代码的形式写出来,希望能抛砖引玉. 一.前言 腾讯微博开放平台授 ...

  5. 微博开放平台SDK 移动端的H5方式授权过程分析

    最近公司要做一个sdk,仿照微博开放平台.要写移动sdk,并且采用H5页面进行授权.看了几天微博SDK源码,终于理解了微博如何做到通过H5页面授权,并回调移动端的方法返回授权码,access Toke ...

  6. 腾讯微博开放平台 android登录界面显示为pc登录界面 解决方案

    腾讯微博开放平台的登录授权一直没有官方的sdk,下载的sdk开始正常使用无问题,但是某天,我们用htc g10  android2.3(有刷过机)使用腾讯微博账号登录,发现登录界面显示为pc上的授权页 ...

  7. Sina微博开放平台获得App key和App secret

    最近由于需要调用微博开放接口,花点时间研究.刚上手,希望与大家多多交流,共同进步.也希望大家多提提意见和建议,感谢. Sina 微博开放平台的 地址是 http://open.t.sina.com.c ...

  8. 关于微博开放平台Oauth2.0接入网站应用

    关于什么是微博开放平台及微博开放平台能做什么,咱就不做搜索引擎的搬运工了 这里直接给个链接介绍:微博开放平台 本文只是抛砖引玉,讲讲微博开放平台的基本用法,适合没接触过开放平台的朋友入门学习,老鸟就略 ...

  9. 微博开放平台SDK使用

    微博开放平台SDK使用 1.注册为开发者 使用新浪微博帐号在http://open.weibo.com/注册开发者,只要完善开发者信息,并完成邮箱验证就可以成为开发者. 2.创建应用 选择要创建的应用 ...

最新文章

  1. vue——props的两种常用方法
  2. 抱怨IT公司人才缺乏?留住现有人才方是正途
  3. python基础-字典(8)
  4. python使用内置方法和修饰器方法获取类名、函数名
  5. 有了容器为什么kubernetes还需要Pod?
  6. Xcode9的xib只支持iOS7.0及以上版本
  7. 在a标签中写ajax,ajax请求后的数据渲染到页面中,a链接失效
  8. RDLC 报表参数、常量及常用表达式的使用方法(上)
  9. 030_磁盘调度策略比较
  10. the 1st one
  11. 运动目标检测——研究现状
  12. 唱响艾泽拉斯_综合篇
  13. 加州大学计算机系统,盘点:美国加州大学系统值得申请的专业
  14. SCAU华南农业大学-数电实验-用74LS283实现2*4乘法器
  15. 博客与计算机相关的内容无法进行查看,博客检索的关键技术研究-计算机科学与技术专业论文.docx...
  16. Docker扩容:Centos8虚拟机硬盘扩容+修改Docker默认存储位置
  17. android 彩信处理
  18. 产品开发:先行动,再研究
  19. 开源代码安全 | 微软是如何应对开源代码安全问题的?
  20. 个人所得税征收计算公式

热门文章

  1. 【Python】72行实现代码行数统计,简单实用~
  2. 唯品会“惊喜”不断:除了杰伦,你还得知道这个
  3. 2023深圳杯(东三省)数学建模C题思路 - 无人机协同避障航迹规划
  4. 3月初中国域名商域名解析量26强:新网跌破百万
  5. 六 面向对象高级属性
  6. 滤波,去耦,旁路电容的选取问题
  7. 【UE4 C++】获取运行时间、设置时间流速、暂停游戏
  8. 结构型 桥模式 -Bridge
  9. PDF 打字机等注释工具能否改变字体颜色大小等属性
  10. D3D学习笔记之十---模型的载入。