ios - programar - Cómo hacer una solicitud HTTP+autenticación básica en Swift
swift vs objective c (8)
// crear la cadena de codificación de la base de autenticación 64
let PasswordString = "/(txtUserName.text):/(txtPassword.text)"
let PasswordData = PasswordString.dataUsingEncoding(NSUTF8StringEncoding)
let base64EncodedCredential = PasswordData!.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.Encoding64CharacterLineLength)
//let base64EncodedCredential = PasswordData!.base64EncodedStringWithOptions(nil)
// crear URL de autenticación
let urlPath: String = "http://...../auth"
var url: NSURL = NSURL(string: urlPath)
// crear e inicializar la solicitud de autenticación básica
var request: NSMutableURLRequest = NSMutableURLRequest(URL: url)
request.setValue("Basic /(base64EncodedCredential)", forHTTPHeaderField: "Authorization")
request.HTTPMethod = "GET"
// Puedes usar uno de los siguientes métodos
// 1 solicitud de URL con NSURLConnectionDataDelegate
let queue:NSOperationQueue = NSOperationQueue()
let urlConnection = NSURLConnection(request: request, delegate: self)
urlConnection.start()
// 2 Solicitud de URL con AsynchronousRequest
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {(response, data, error) in
println(NSString(data: data, encoding: NSUTF8StringEncoding))
}
// 2 Solicitud de URL con AsynchronousRequest con salida json
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler:{ (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in
var err: NSError
var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
println("/(jsonResult)")
})
// 3 Solicitud de URL con SynchronousRequest
var response: AutoreleasingUnsafePointer<NSURLResponse?>=nil
var dataVal: NSData = NSURLConnection.sendSynchronousRequest(request, returningResponse: response, error:nil)
var err: NSError
var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(dataVal, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
println("/(jsonResult)")
// 4 Solicitud de URL con NSURLSession
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let authString = "Basic /(base64EncodedCredential)"
config.HTTPAdditionalHeaders = ["Authorization" : authString]
let session = NSURLSession(configuration: config)
session.dataTaskWithURL(url) {
(let data, let response, let error) in
if let httpResponse = response as? NSHTTPURLResponse {
let dataString = NSString(data: data, encoding: NSUTF8StringEncoding)
println(dataString)
}
}.resume()
// puede recibir un error fatal si cambió la solicitud.HTTPMethod = "POST" cuando el servidor solicitó la solicitud GET
Tengo un servicio REST Full con autenticación básica y deseo invocarlo desde iOS + swift. ¿Cómo y dónde debo proporcionar la credencial para esta solicitud?
Mi código (lo siento, solo empiezo a aprender iOS / obj-c / swift):
class APIProxy: NSObject {
var data: NSMutableData = NSMutableData()
func connectToWebApi() {
var urlPath = "http://xx.xx.xx.xx/BP3_0_32/ru/hs/testservis/somemethod"
NSLog("connection string /(urlPath)")
var url: NSURL = NSURL(string: urlPath)
var request = NSMutableURLRequest(URL: url)
let username = "hs"
let password = "1"
let loginString = NSString(format: "%@:%@", username, password)
let loginData: NSData = loginString.dataUsingEncoding(NSUTF8StringEncoding)
let base64LoginString = loginData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.fromMask(0))
request.setValue(base64LoginString, forHTTPHeaderField: "Authorization")
var connection: NSURLConnection = NSURLConnection(request: request, delegate: self)
connection.start()
}
//NSURLConnection delegate method
func connection(connection: NSURLConnection!, didFailWithError error: NSError!) {
println("Failed with error:/(error.localizedDescription)")
}
//NSURLConnection delegate method
func connection(didReceiveResponse: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {
//New request so we need to clear the data object
self.data = NSMutableData()
}
//NSURLConnection delegate method
func connection(connection: NSURLConnection!, didReceiveData data: NSData!) {
//Append incoming data
self.data.appendData(data)
}
//NSURLConnection delegate method
func connectionDidFinishLoading(connection: NSURLConnection!) {
NSLog("connectionDidFinishLoading");
}
}
En Swift 2:
extension NSMutableURLRequest {
func setAuthorizationHeader(username username: String, password: String) -> Bool {
guard let data = "/(username):/(password)".dataUsingEncoding(NSUTF8StringEncoding) else { return false }
let base64 = data.base64EncodedStringWithOptions([])
setValue("Basic /(base64)", forHTTPHeaderField: "Authorization")
return true
}
}
Llamaré a json al hacer clic en el botón de inicio de sesión
@IBAction func loginClicked(sender : AnyObject){
var request = NSMutableURLRequest(URL: NSURL(string: kLoginURL)) // Here, kLogin contains the Login API.
var session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(self.criteriaDic(), options: nil, error: &err) // This Line fills the web service with required parameters.
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
// println("Response: /(response)")
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Body: /(strData)")
var err1: NSError?
var json2 = NSJSONSerialization.JSONObjectWithData(strData.dataUsingEncoding(NSUTF8StringEncoding), options: .MutableLeaves, error:&err1 ) as NSDictionary
println("json2 :/(json2)")
if(err) {
println(err!.localizedDescription)
}
else {
var success = json2["success"] as? Int
println("Succes: /(success)")
}
})
task.resume()
}
Aquí, he hecho un diccionario separado para los parámetros.
var params = ["format":"json", "MobileType":"IOS","MIN":"f8d16d98ad12acdbbe1de647414495ec","UserName":emailTxtField.text,"PWD":passwordTxtField.text,"SigninVia":"SH"]as NSDictionary
return params
}
Proporciona credenciales en una instancia de URLRequest
, como esta en Swift 3:
let username = "user"
let password = "pass"
let loginString = String(format: "%@:%@", username, password)
let loginData = loginString.data(using: String.Encoding.utf8)!
let base64LoginString = loginData.base64EncodedString()
// create the request
let url = URL(string: "http://www.example.com/")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Basic /(base64LoginString)", forHTTPHeaderField: "Authorization")
// fire off the request
// make sure your class conforms to NSURLConnectionDelegate
let urlConnection = NSURLConnection(request: request, delegate: self)
O en NSMutableURLRequest
en Swift 2:
// set up the base64-encoded credentials
let username = "user"
let password = "pass"
let loginString = NSString(format: "%@:%@", username, password)
let loginData: NSData = loginString.dataUsingEncoding(NSUTF8StringEncoding)!
let base64LoginString = loginData.base64EncodedStringWithOptions([])
// create the request
let url = NSURL(string: "http://www.example.com/")
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
request.setValue("Basic /(base64LoginString)", forHTTPHeaderField: "Authorization")
// fire off the request
// make sure your class conforms to NSURLConnectionDelegate
let urlConnection = NSURLConnection(request: request, delegate: self)
Tuve un problema similar al intentar enviar a MailGun para algunos correos electrónicos automáticos que estaba implementando en una aplicación.
Pude hacer que esto funcionara correctamente con una gran respuesta HTTP. Puse la ruta completa en Keys.plist para que pueda subir mi código a github y descomponer algunos de los argumentos en variables para que pueda programarlos más adelante en el futuro.
// Email the FBO with desired information
// Parse our Keys.plist so we can use our path
var keys: NSDictionary?
if let path = NSBundle.mainBundle().pathForResource("Keys", ofType: "plist") {
keys = NSDictionary(contentsOfFile: path)
}
if let dict = keys {
// variablize our https path with API key, recipient and message text
let mailgunAPIPath = dict["mailgunAPIPath"] as? String
let emailRecipient = "[email protected]"
let emailMessage = "Testing%20email%20sender%20variables"
// Create a session and fill it with our request
let session = NSURLSession.sharedSession()
let request = NSMutableURLRequest(URL: NSURL(string: mailgunAPIPath! + "from=FBOGo%20Reservation%20%3Cscheduler@<my domain>.com%3E&to=reservations@<my domain>.com&to=/(emailRecipient)&subject=A%20New%20Reservation%21&text=/(emailMessage)")!)
// POST and report back with any errors and response codes
request.HTTPMethod = "POST"
let task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
if let error = error {
print(error)
}
if let response = response {
print("url = /(response.URL!)")
print("response = /(response)")
let httpResponse = response as! NSHTTPURLResponse
print("response code = /(httpResponse.statusCode)")
}
})
task.resume()
}
La ruta de Mailgun está en Keys.plist como una cadena llamada mailgunAPIPath con el valor:
https://API:key-<my key>@api.mailgun.net/v3/<my domain>.com/messages?
Espero que esto ayude a ofrecer una solución a alguien que intenta evitar el uso de código de terceros para sus solicitudes de POST.
mi solución funciona de la siguiente manera:
import UIKit
class LoginViewController: UIViewController, NSURLConnectionDataDelegate {
@IBOutlet var usernameTextField: UITextField
@IBOutlet var passwordTextField: UITextField
@IBAction func login(sender: AnyObject) {
var url = NSURL(string: "YOUR_URL")
var request = NSURLRequest(URL: url)
var connection = NSURLConnection(request: request, delegate: self, startImmediately: true)
}
func connection(connection:NSURLConnection!, willSendRequestForAuthenticationChallenge challenge:NSURLAuthenticationChallenge!) {
if challenge.previousFailureCount > 1 {
} else {
let creds = NSURLCredential(user: usernameTextField.text, password: passwordTextField.text, persistence: NSURLCredentialPersistence.None)
challenge.sender.useCredential(creds, forAuthenticationChallenge: challenge)
}
}
func connection(connection:NSURLConnection!, didReceiveResponse response: NSURLResponse) {
let status = (response as NSHTTPURLResponse).statusCode
println("status code is /(status)")
// 200? Yeah authentication was successful
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Puede usar esta clase como la implementación de un ViewController. Conecte sus campos a los vars anotados IBOutlet y su botón a la función anotada IBAction.
Explicación: En el inicio de sesión de funciones, crea su solicitud con NSURL, NSURLRequest y NSURLConnection. Esencial aquí es el delegado que hace referencia a esta clase (uno mismo). Para recibir las llamadas de los delegados, necesita
- Agregue el protocolo NSURLConnectionDataDelegate a la clase
- Implemente la conexión de la función de los protocolos: willSendRequestForAuthenticationChallenge "Esto se usa para agregar las credenciales a la solicitud
- Implementar la función de los protocolos "conexión: didReceiveResponse" Esto verificará el código de estado de respuesta http
ve claro para SWIFT 3 y APACHE simple Auth:
func urlSession(_ session: URLSession, task: URLSessionTask,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
let credential = URLCredential(user: "test",
password: "test",
persistence: .none)
completionHandler(.useCredential, credential)
}
veloz 4:
let username = "username"
let password = "password"
let loginString = "/(username):/(password)"
guard let loginData = loginString.data(using: String.Encoding.utf8) else {
return
}
let base64LoginString = loginData.base64EncodedString()
request.httpMethod = "GET"
request.setValue("Basic /(base64LoginString)", forHTTPHeaderField: "Authorization")