对于我大学的简单iOS(swift)应用程序,我尝试登录其中一个页面以检索当前卡上的金额。但是,在执行我的http请求时,我无法获得所需的数据。
这是我的代码:
let url = NSURL(string: "https://campuscard.hhs.nl/portal/j_spring_security_check")
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
let data : NSData = ("?j_username=USERNAME&j_password=PASSWORD").dataUsingEncoding(NSUTF8StringEncoding)!;
request.HTTPBody = data;
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {(response, data, error) in
println(NSString(data: data, encoding: NSUTF8StringEncoding))
}
它给了我错误,我输入了错误的凭据,当我打印我的请求时,它说:
<NSMutableURLRequest: 0x7f8d7b53bd30> { URL: https://campuscard.hhs.nl/portal/j_spring_security_check, headers: {
"Content-Type" = "application/x-www-form-urlencoded";
} }
所以我认为它不包括用户名和密码。
有没有人有想法?
我和我大学的其他学生会非常感激!
加入
我和我班上的一位朋友通过Charles感谢请求中的属性,但是因为我们都没有尝试过这个,所以我们不知道如何处理这些属性。我们只是添加了我们可以找到的所有请求并尝试了它,但我们仍然在服务器上获得ArrayOutOfBoundsException。
var dataString = "j_username=USERNAME&j_password=PASSWORD"
var request : NSMutableURLRequest = NSMutableURLRequest()
request.URL = NSURL(string: "https://campuscard.hhs.nl/portal/j_spring_security_check")
var postString = (dataString as NSString).dataUsingEncoding(NSUTF8StringEncoding)
request.HTTPMethod = "POST"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
//request.setValue("JSESSIONID=C78C688403A836968EC1FEAED9AE9126", forHTTPHeaderField: "Cookie")
request.setValue("campuscard.hhs.nl", forHTTPHeaderField: "Host");
request.setValue("keep-alive", forHTTPHeaderField: "Connection");
request.setValue("41", forHTTPHeaderField: "Content-Length");
request.setValue("max-age=0", forHTTPHeaderField: "Cache-Controle");
request.setValue("text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", forHTTPHeaderField: "Accept");
request.setValue("https://campuscard.hhs.nl", forHTTPHeaderField: "Origin");
request.setValue("https://campuscard.hhs.nl/portal/login", forHTTPHeaderField: "Referer");
request.setValue("gzip,deflate", forHTTPHeaderField: "Accept-Encoding");
request.setValue("nl-NL,nl;q=0.8,en-US;q=0.6,en;q=0.4", forHTTPHeaderField: "Accept-Language");
request.HTTPBody = postString
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {(response, data, error) in
println(NSString(data: data, encoding: NSUTF8StringEncoding))
}
我很遗憾在你身上放置如此大的代码,但也许有些东西你可以看到是错的。谢谢你的时间
答案 0 :(得分:6)
x-www-form-urlencoded
请求的正文不应包含?
。
另外,您应该是USERNAME
和PASSWORD
的编码百分比。现在,如果(更可能是密码)包含某些保留字符,您的请求将失败。我在Swift 2中使用了这样的扩展名:
extension String {
/// Percent escape value to be added to a HTTP request
///
/// This percent-escapes all characters besize the alphanumeric character set and "-", ".", "_", and "*".
/// This will also replace spaces with the "+" character as outlined in the application/x-www-form-urlencoded spec:
///
/// http://www.w3.org/TR/html5/forms.html#application/x-www-form-urlencoded-encoding-algorithm
///
/// - returns: Return percent escaped string.
func stringByAddingPercentEncodingForFormUrlencoded() -> String? {
let allowedCharacters = NSCharacterSet(charactersInString: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._* ")
return stringByAddingPercentEncodingWithAllowedCharacters(allowedCharacters)?.stringByReplacingOccurrencesOfString(" ", withString: "+")
}
}
我在stringByAddingPercentEncodingForFormUrlencoded
和USERNAME
值上使用此PASSWORD
函数(但不是整个字符串)。
或者,在Swift 3中:
extension String {
/// Percent escape value to be added to a HTTP request
///
/// This percent-escapes all characters besize the alphanumeric character set and "-", ".", "_", and "*".
/// This will also replace spaces with the "+" character as outlined in the application/x-www-form-urlencoded spec:
///
/// http://www.w3.org/TR/html5/forms.html#application/x-www-form-urlencoded-encoding-algorithm
///
/// - returns: Return percent escaped string.
func addingPercentEncodingForFormUrlencoded() -> String? {
let allowedCharacters = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._* ")
return addingPercentEncoding(withAllowedCharacters: allowedCharacters)?.replacingOccurrences(of: " ", with: "+")
}
}
检查NSURLRequest
时缺少用户名和密码并不令人担心(我不希望它在您按日志时包含请求正文)。如果要检查,请通过Charles或类似的方式运行此操作。
如果您正在使用Charles,如果要检查HTTPS交互,则必须启用SSL代理,并将您的域添加到位置列表中。请参阅“代理”菜单上的“代理设置...”,然后单击“SSL”选项卡。见Charles Web Debugging Proxy。
这将向您展示其所有荣耀的完整要求。如果您尝试让您的应用程序像在Web浏览器中一样登录,则可以使用Charles观看Web浏览器交换,并将其与您的应用进行比较和对比。
在修订后的问题中,您现在显示了您尝试设置的所有各种标题。 (您不必设置其中一些:在Charles中观看现有应用程序请求,您将看到其中一些已经设置。)如果需要其中任何一个,我会感到惊讶。
具有讽刺意味的是,唯一一个可能很关键的是你注释掉的那个,JSESSIONID。大声笑。许多这些网站将在登录HTML中提供一些会话ID。然后,当您尝试提交登录请求时,您必须传递登录HTML页面提供给您的相同JSESSIONID
。
所以模型通常是(a)获取登录页面; (b)根据你的例子,解析需要在后续请求中设置的任何标题字段(例如看起来可能是JSESSIONID
); (c)为所有后续请求提供该会话ID。
这是假设,因为我无法在网络浏览器和您的特定网络服务器上实际看到完整的对话,但这是我之前见过的那种模式。只需观看Web浏览器请求/响应,特别注意隐藏在HTML中的隐藏ID号码,这些ID号码可能会在后续请求中提供(在正文或标题中)。