LeoChen98 / BiliAccount

基于.net standard的B站账号操作封装。|A .net standard library for bilibili account operations.(like login and sso)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

SSO貌似有点问题?另外刷token时不顺带更新token和cookie吗?

pjy612 opened this issue · comments

调用SSO貌似有点问题。。。提示302异常然后没返回值。
另外刷新token时只更新了时间。不顺带返回更新token和cookie吗?

SSO返回一个object[4] | [0]=>(string)strCookies,[1]=>(string)csrf_token,[2]=>(DateTime)Expiress,[3]=>(CookieCollection)Cookies
testproject的var_dump出不来,但是值是有的。

刷新token的话要在token失效前刷新,刷新后token本身是不变的,返回时间,至于cookies可以调SSO,这是破站后端的逻辑,它接口返回不带cookies我就没给他集成,反正你多调一个SSO和我默认调SSO消耗是一样的。

SSO返回一个object[4] | [0]=>(string)strCookies,[1]=>(string)csrf_token,[2]=>(DateTime)Expiress,[3]=>(CookieCollection)Cookies
testproject的var_dump出不来,但是值是有的。

刷新token的话要在token失效前刷新,刷新后token本身是不变的,返回时间,至于cookies可以调SSO,这是破站后端的逻辑,它接口返回不带cookies我就没给他集成,反正你多调一个SSO和我默认调SSO消耗是一样的。

没 我是说 刷新 token 的接口 里面返回的数据 里面包含了 新的 cookies 好像,所以好奇不直接集成一下吗?
另外是因为SSO好像报了个302的异常我没拿到返回值。晚点我再试试。

SSO返回一个object[4] | [0]=>(string)strCookies,[1]=>(string)csrf_token,[2]=>(DateTime)Expiress,[3]=>(CookieCollection)Cookies
testproject的var_dump出不来,但是值是有的。
刷新token的话要在token失效前刷新,刷新后token本身是不变的,返回时间,至于cookies可以调SSO,这是破站后端的逻辑,它接口返回不带cookies我就没给他集成,反正你多调一个SSO和我默认调SSO消耗是一样的。

没 我是说 刷新 token 的接口 里面返回的数据 里面包含了 新的 cookies 好像,所以好奇不直接集成一下吗?
另外是因为SSO好像报了个302的异常我没拿到返回值。晚点我再试试。

302是正常的,cookies返回在Set-Cookies里

这 SSO 真的能用吗? 返回值拿不到啊 直接 异常了
我把代码下下移除几个不用的依赖 然后 用 VS2019跑了下 又没报错 囧。。。
我拿代码 跑下吧 。。。愁

还是换这个接口吧 = =。一下搞定

public static bool RefreshToken(string access_token, string refresh_token,ref Account account)
        {
            string parm = "access_token=" + access_token + "&appkey=" + Config.Instance.Appkey + "&refresh_token=" + refresh_token + "&ts=" + TimeStamp;
            parm += "&sign=" + GetSign(parm);
            string str = Http.PostBody("https://passport.bilibili.com/api/v2/oauth2/refresh_token", parm);

            if (!string.IsNullOrEmpty(str))
            {
#if NETSTANDARD2_0 || NETCORE3_0
                RefreshToken_DataTemplete obj = JsonConvert.DeserializeObject<RefreshToken_DataTemplete>(str);
#else
                RefreshToken_DataTemplete obj = (new JavaScriptSerializer()).Deserialize<RefreshToken_DataTemplete>(str);
#endif
                if (obj.code == 0)
                {
                    account.Uid = obj.data.token_info.mid;
                    account.AccessToken = obj.data.token_info.access_token;
                    account.RefreshToken = obj.data.token_info.refresh_token;
                    account.Expires_AccessToken = DateTime.Parse("1970-01-01 08:00:00").AddSeconds(obj.ts + obj.data.token_info.expires_in);

                    account.Cookies = new CookieCollection();
                    foreach (RefreshToken_DataTemplete.Data_Templete.Cookie_Info_Templete.Cookie_Templete i in obj.data.cookie_info.cookies)
                    {
                        account.strCookies += i.name + "=" + i.value + "; ";
                        account.Cookies.Add(new Cookie(i.name, i.value) { Domain = ".bilibili.com" });
                        account.Expires_Cookies = DateTime.Parse("1970-01-01 08:00:00").AddSeconds(i.expires);

                        if (i.name == "bili_jct")
                            account.CsrfToken = i.value;
                    }
                    account.strCookies = account.strCookies.Substring(0, account.strCookies.Length - 2);
                    return true;
                }
            }
            return false;
        }

private class RefreshToken_DataTemplete
        {
            #region Public Fields

            public int code;
            public Data_Templete data;
            public long ts;

            #endregion Public Fields

            #region Public Classes

            public class Data_Templete
            {
                #region Public Fields

                public Token_Info_Templete token_info;
                public Cookie_Info_Templete cookie_info;

                #endregion Public Fields

                #region Public Classes
                public class Token_Info_Templete
                {
                    #region Public Fields

                    public string access_token;
                    public long expires_in;
                    public string mid;
                    public string refresh_token;

                    #endregion Public Fields
                }

                public class Cookie_Info_Templete
                {
                    #region Public Fields

                    public Cookie_Templete[] cookies;

                    #endregion Public Fields

                    #region Public Classes

                    public class Cookie_Templete
                    {
                        #region Public Fields

                        public long expires;
                        public string name;
                        public string value;

                        #endregion Public Fields
                    }

                    #endregion Public Classes
                }
                #endregion Public Classes
            }

            #endregion Public Classes
        }

SSO原理是请求了接口之后服务器会返回一个302的包,返回包的header里包含了Set-Cookies头从而设置cookies

SSO原理是请求了接口之后服务器会返回一个302的包,返回包的header里包含了Set-Cookies头从而设置cookies

image

VS2019 以下 的一些 版本,302 会触发 一个 WebException 异常。因为 代码中没捕获,所以 在一些 低版本的环境上运行 SSO 会直接报错。
推荐 捕获一下 然后再 从 WebException 取 Response。

try
{
    req = (HttpWebRequest)WebRequest.Create("https://passport.bilibili.com/api/login/sso?" + parm);
    req.AllowAutoRedirect = false;
    req.UserAgent = Config.Instance.User_Agent;
    rep = (HttpWebResponse)req.GetResponse();

    foreach (string i in rep.Headers.GetValues("Set-Cookie"))
    {
        string[] tmp = i.Split(';');
        string[] tmp2 = tmp[0].Split('=');

        cookies += tmp[0] + "; ";
        cookiesC.Add(new Cookie(tmp2[0], tmp2[1]) { Domain = ".bilibili.com" });
        expires = DateTime.Parse(tmp[2].Split('=')[1]);

        if (tmp2[0] == "bili_jct")
            csrf_token = tmp2[1];
    }
    cookies = cookies.Substring(0, cookies.Length - 2);
}
catch (WebException webException)
{
    rep = (HttpWebResponse)webException.Response;
    foreach (string i in rep.Headers.GetValues("Set-Cookie"))
    {
        string[] tmp = i.Split(';');
        string[] tmp2 = tmp[0].Split('=');

        cookies += tmp[0] + "; ";
        cookiesC.Add(new Cookie(tmp2[0], tmp2[1]) { Domain = ".bilibili.com" });
        expires = DateTime.Parse(tmp[2].Split('=')[1]);

        if (tmp2[0] == "bili_jct")
            csrf_token = tmp2[1];
    }
    cookies = cookies.Substring(0, cookies.Length - 2);
}
finally
{
    if (rep != null) rep.Close();
    if (req != null) req.Abort();
}

当然 换成 /api/v2/oauth2/refresh_token 直接一劳永逸...