1
- using System ;
2
- using System . Collections . Generic ;
1
+ using System . Collections . Generic ;
2
+ using System . Json ;
3
3
using System . Net . Http ;
4
- using System . Text . RegularExpressions ;
5
4
using System . Threading . Tasks ;
6
5
7
6
namespace Berrysoft . Tsinghua . Net
@@ -14,8 +13,7 @@ public abstract class AuthHelper : NetHelperBase, IConnect
14
13
private const string LogUriBase = "https://auth{0}.tsinghua.edu.cn/cgi-bin/srun_portal" ;
15
14
private const string FluxUriBase = "https://auth{0}.tsinghua.edu.cn/rad_user_info.php" ;
16
15
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 } ;
19
17
private readonly string LogUri ;
20
18
private readonly string FluxUri ;
21
19
private readonly string ChallengeUri ;
@@ -61,66 +59,95 @@ internal AuthHelper(string username, string password, HttpClient client, int ver
61
59
/// Login to the network.
62
60
/// </summary>
63
61
/// <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
+
65
74
/// <summary>
66
75
/// Logout from the network.
67
76
/// </summary>
68
77
/// <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
+
78
90
/// <summary>
79
91
/// Get information of the user online.
80
92
/// </summary>
81
93
/// <returns>An instance of <see cref="FluxUser"/> class of the current user.</returns>
82
94
public async Task < FluxUser > GetFluxAsync ( ) => FluxUser . Parse ( await PostAsync ( FluxUri ) ) ;
83
95
84
- private static readonly Regex ChallengeRegex = new Regex ( @"""challenge"":""(.*?)""" ) ;
85
96
/// <summary>
86
97
/// Get "challenge" to encode the password.
87
98
/// </summary>
88
99
/// <returns>The content of the website.</returns>
89
100
private async Task < string > GetChallengeAsync ( )
90
101
{
91
102
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" ] ;
94
105
}
95
106
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}" ;
99
109
/// <summary>
100
110
/// Get login data with username, password and "challenge".
101
111
/// </summary>
102
112
/// <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 )
104
114
{
105
- //const string passwordMD5 = "5e543256c480ac577d30f76f9120eb74";
106
115
string token = await GetChallengeAsync ( ) ;
107
116
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 >
109
119
{
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
+ } ;
124
151
}
125
152
}
126
153
/// <summary>
0 commit comments