1- using System ;
2- using System . Collections . Generic ;
1+ using System . Collections . Generic ;
2+ using System . Json ;
33using System . Net . Http ;
4- using System . Text . RegularExpressions ;
54using System . Threading . Tasks ;
65
76namespace Berrysoft . Tsinghua . Net
@@ -14,8 +13,7 @@ public abstract class AuthHelper : NetHelperBase, IConnect
1413 private const string LogUriBase = "https://auth{0}.tsinghua.edu.cn/cgi-bin/srun_portal" ;
1514 private const string FluxUriBase = "https://auth{0}.tsinghua.edu.cn/rad_user_info.php" ;
1615 private const string ChallengeUriBase = "https://auth{0}.tsinghua.edu.cn/cgi-bin/get_challenge?username={{0}}&double_stack=1&ip&callback=callback" ;
17- private const string LogoutData = "action=logout" ;
18- private const string LogoutUserData = "action=logout&username={0}" ;
16+ private static readonly int [ ] AcIds = new int [ ] { 1 , 25 , 33 , 35 } ;
1917 private readonly string LogUri ;
2018 private readonly string FluxUri ;
2119 private readonly string ChallengeUri ;
@@ -61,66 +59,95 @@ internal AuthHelper(string username, string password, HttpClient client, int ver
6159 /// Login to the network.
6260 /// </summary>
6361 /// <returns>The response of the website.</returns>
64- public async Task < string > LoginAsync ( ) => await PostAsync ( LogUri , await GetLoginDataAsync ( ) ) ;
62+ public async Task < LogResponse > LoginAsync ( )
63+ {
64+ LogResponse response = null ;
65+ foreach ( int ac_id in AcIds )
66+ {
67+ response = LogResponse . ParseFromAuth ( await PostAsync ( LogUri , await GetLoginDataAsync ( ac_id ) ) ) ;
68+ if ( response . Succeed )
69+ break ;
70+ }
71+ return response ;
72+ }
73+
6574 /// <summary>
6675 /// Logout from the network.
6776 /// </summary>
6877 /// <returns>The response of the website.</returns>
69- public Task < string > LogoutAsync ( ) => PostAsync ( LogUri , LogoutData ) ;
70- /// <summary>
71- /// Logout from the network with the specified username.
72- /// When a user logged in through <see cref="AuthHelper"/> and logged out through <see cref="NetHelper"/>,
73- /// he should call this method with his username explicitly, or he can't logout.
74- /// </summary>
75- /// <param name="username">The specified username.</param>
76- /// <returns>The response of the website.</returns>
77- public Task < string > LogoutAsync ( string username ) => PostAsync ( LogUri , string . Format ( LogoutUserData , username ) ) ;
78+ public async Task < LogResponse > LogoutAsync ( )
79+ {
80+ LogResponse response = null ;
81+ foreach ( int ac_id in AcIds )
82+ {
83+ response = LogResponse . ParseFromAuth ( await PostAsync ( LogUri , await GetLogoutDataAsync ( ac_id ) ) ) ;
84+ if ( response . Succeed )
85+ break ;
86+ }
87+ return response ;
88+ }
89+
7890 /// <summary>
7991 /// Get information of the user online.
8092 /// </summary>
8193 /// <returns>An instance of <see cref="FluxUser"/> class of the current user.</returns>
8294 public async Task < FluxUser > GetFluxAsync ( ) => FluxUser . Parse ( await PostAsync ( FluxUri ) ) ;
8395
84- private static readonly Regex ChallengeRegex = new Regex ( @"""challenge"":""(.*?)""" ) ;
8596 /// <summary>
8697 /// Get "challenge" to encode the password.
8798 /// </summary>
8899 /// <returns>The content of the website.</returns>
89100 private async Task < string > GetChallengeAsync ( )
90101 {
91102 string result = await GetAsync ( string . Format ( ChallengeUri , Username ) ) ;
92- Match match = ChallengeRegex . Match ( result ) ;
93- return match . Groups [ 1 ] . Value ;
103+ JsonValue json = JsonValue . Parse ( result . Substring ( 9 , result . Length - 10 ) ) ;
104+ return json [ "challenge" ] ;
94105 }
95106
96- private Dictionary < string , string > logDataDictionary ;
97- private const string LoginInfoJson = "{{\" ip\" : \" \" , \" acid\" : \" 1\" , \" enc_ver\" : \" srun_bx1\" , \" username\" : \" {0}\" , \" password\" : \" {1}\" }}" ;
98- private const string ChkSumData = "{0}{1}{0}{2}{0}1{0}{0}200{0}1{0}{3}" ;
107+ private const string LoginInfoJson = "{{\" username\" : \" {0}\" , \" password\" : \" {1}\" , \" ip\" : \" \" , \" acid\" : \" {2}\" , \" enc_ver\" : \" srun_bx1\" }}" ;
108+ private const string ChkSumData = "{0}{1}{0}{2}{0}{4}{0}{0}200{0}1{0}{3}" ;
99109 /// <summary>
100110 /// Get login data with username, password and "challenge".
101111 /// </summary>
102112 /// <returns>A dictionary contains the data.</returns>
103- private async Task < Dictionary < string , string > > GetLoginDataAsync ( )
113+ private async Task < Dictionary < string , string > > GetLoginDataAsync ( int ac_id )
104114 {
105- //const string passwordMD5 = "5e543256c480ac577d30f76f9120eb74";
106115 string token = await GetChallengeAsync ( ) ;
107116 string passwordMD5 = CryptographyHelper . GetHMACMD5 ( token ) ;
108- if ( logDataDictionary == null )
117+ string info = "{SRBX1}" + CryptographyHelper . Base64Encode ( CryptographyHelper . XEncode ( string . Format ( LoginInfoJson , Username , Password , ac_id ) , token ) ) ;
118+ return new Dictionary < string , string >
109119 {
110- logDataDictionary = new Dictionary < string , string >
111- {
112- [ "ac_id" ] = "1" ,
113- [ "double_stack" ] = "1" ,
114- [ "n" ] = "200" ,
115- [ "type" ] = "1"
116- } ;
117- }
118- logDataDictionary [ "action" ] = "login" ;
119- logDataDictionary [ "password" ] = "{MD5}" + passwordMD5 ;
120- logDataDictionary [ "info" ] = "{SRBX1}" + CryptographyHelper . Base64Encode ( CryptographyHelper . XEncode ( string . Format ( LoginInfoJson , Username , Password ) , token ) ) ;
121- logDataDictionary [ "username" ] = Username ;
122- logDataDictionary [ "chksum" ] = CryptographyHelper . GetSHA1 ( string . Format ( ChkSumData , token , Username , passwordMD5 , logDataDictionary [ "info" ] ) ) ;
123- return logDataDictionary ;
120+ [ "action" ] = "login" ,
121+ [ "ac_id" ] = ac_id . ToString ( ) ,
122+ [ "double_stack" ] = "1" ,
123+ [ "n" ] = "200" ,
124+ [ "type" ] = "1" ,
125+ [ "username" ] = Username ,
126+ [ "password" ] = "{MD5}" + passwordMD5 ,
127+ [ "info" ] = info ,
128+ [ "chksum" ] = CryptographyHelper . GetSHA1 ( string . Format ( ChkSumData , token , Username , passwordMD5 , info , ac_id ) ) ,
129+ [ "callback" ] = "callback"
130+ } ;
131+ }
132+
133+ private const string LogoutInfoJson = "{{\" username\" : \" {0}\" , \" ip\" : \" \" , \" acid\" : \" {1}\" , \" enc_ver\" : \" srun_bx1\" }}" ;
134+ private const string LogoutChkSumData = "{0}{1}{0}{3}{0}{0}200{0}1{0}{2}" ;
135+ private async Task < Dictionary < string , string > > GetLogoutDataAsync ( int ac_id )
136+ {
137+ string token = await GetChallengeAsync ( ) ;
138+ string info = "{SRBX1}" + CryptographyHelper . Base64Encode ( CryptographyHelper . XEncode ( string . Format ( LogoutInfoJson , Username , ac_id ) , token ) ) ;
139+ return new Dictionary < string , string >
140+ {
141+ [ "action" ] = "logout" ,
142+ [ "ac_id" ] = ac_id . ToString ( ) ,
143+ [ "double_stack" ] = "1" ,
144+ [ "n" ] = "200" ,
145+ [ "type" ] = "1" ,
146+ [ "username" ] = Username ,
147+ [ "info" ] = info ,
148+ [ "chksum" ] = CryptographyHelper . GetSHA1 ( string . Format ( LogoutChkSumData , token , Username , info , ac_id ) ) ,
149+ [ "callback" ] = "callback"
150+ } ;
124151 }
125152 }
126153 /// <summary>
0 commit comments