How to connect to self signed servers using Alamofire 1.3
There is a way to change the Server Trust Policy of the Alamofire manager shared instance, but it's not recommended. Instead you should create your own customised instance of the manager. Here is the recommended solution, code is Swift 2.0 with Alamofire from swift-2.0 branch, compiled in Xcode7 beta 5.
Creating customised instance of the manager
Because you will not use the request method on the Alamofire, but use the one on your custom manager instead, you need to think of where to store the manager. What I do is to store it as static in my networking wrapper (the class that utilizes Alamofire and deals with my application networking needs). I set it up like this:
private static var Manager : Alamofire.Manager = {
// Create the server trust policies
let serverTrustPolicies: [String: ServerTrustPolicy] = [
"maskeddomain.com": .DisableEvaluation
]
// Create custom manager
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
configuration.HTTPAdditionalHeaders = Alamofire.Manager.defaultHTTPHeaders
let man = Alamofire.Manager(
configuration: NSURLSessionConfiguration.defaultSessionConfiguration(),
serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
)
return man
}()
Next step is to switch all your calls that use Alamofire.request()
with Manager.request()
, so you should have something like this:
Manager.request(.GET, "http://stackoverflow.com").responseJSON(
completionHandler: { (_, respose, result) -> Void in
if result.isSuccess {
// enjoy your success
} else if result.isFailure {
// deal with your failure
}
})
If you want to change the shared instance of the manager anyway, go here for more info.
How can I make Alamofire perform HTTPS request, using a certificate self-signed by an Unknown CA?
First you need to include your self signed ssl certificate in your apps target.
Note: The certificate must be in a format that iOS can read. You may need to convert your truststore-root.cer
file to a different format. In some cases this is a trial and error procedure.
Then you can adjust your code to use the convenient certificates(in:)
function of ServerTrustPolicy
like this:
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: ServerTrustPolicy.certificates(),
validateCertificateChain: true,
validateHost: false
)
let serverTrustPolicies = [
"192.168.50.31": serverTrustPolicy
]
return Alamofire.SessionManager(
configuration: configuration,
serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
)
This function will scan your main bundle and return all the included files with one of the following suffixes ".cer", ".CER", ".crt", ".CRT", ".der", ".DER".
UPDATE: You can follow this answer to download your ssl certificate from the terminal. Then double click it to import it to your Keychain. Finaly you can export your certificate from the Keychain as a .cer file. This has the correct format that iOS can read. Verify that this is the case by manually invoking the certificates(in:)
function of ServerTrustPolicy
. It should now return your certificate.
How to implement self signed certificates in Alamofire?
This feature is not yet supported by Alamofire. It will most likely be added eventually by the community, but that work has yet to be submitted to the project. If you feel like contributing this feature, by all means fork the repo and submit a pull request.
If you want to learn how to implement this feature yourself, I'd suggest you read up on SSL pinning and TLS verification on iOS. You could also browse the source code in AFNetworking to get a feel of how it could possibly be implemented.
If you do not have time to build this feature yourself, then I suggest you use AFNetworking for the time being in your Swift app. AFNetworking is perfectly compatible with Swift and does support TLS verification.
How Can I Access Local Https with invalid certificate With Alamofire?
I finally sorted out my problems. There were two problems.
1. I needed to declare sessionManager outside the function.
let manager = SessionManager(configuration: URLSessionConfiguration.default, serverTrustPolicyManager: ServerTrustPolicyManager(policies:["localhost":.disableEvaluation]))
2. I read somewhere that you need to include port number for the host, but that actually caused the problem for me.
It seems like you just need to write "localhost" Instead of "localhost:443".
Regardless, here is the entire code that will disable evaluation for all addresses.
You don't need to change anything to Info.plist. The default Info.plist that Xcode gives you seem to work.
IOS 10.3.2, Xcode 8.3.2, Alamofire Master branch from Github (2017-05-23)
import UIKit
import Alamofire
class ViewController: UIViewController {
open class MyServerTrustPolicyManager: ServerTrustPolicyManager {
open override func serverTrustPolicy(forHost host: String) -> ServerTrustPolicy? {
return ServerTrustPolicy.disableEvaluation
}
}
let sessionManager = SessionManager(delegate:SessionDelegate(), serverTrustPolicyManager:MyServerTrustPolicyManager(policies: [:]))
func connect() {
let user = "user"
let password = "password"
let parameters:Parameters = ["parameter1":"value1", "parameter2":"value2"]
sessionManager.request("https://localhost:443/index.php", parameters:parameters).authenticate(user:user, password:password).responseString {
response in
debugPrint(response.result.value)
} else {
debugPrint(response)
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
connect()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Alamofire 5 with self-signed certificate
It's very similar in Alamofire 5 but ServerTrustPolicy
has been refactored into a protocol with conforming types for better extensibility. Similar to the answer you linked, you'll need to create a ServerTrustManager
for your domain:
let manager = ServerTrustManager(evaluators: ["your.domain.here": DisabledTrustEvaluator()])
let session = Session(serverTrustManager: manager)
Of course, you'll still need to add ATS exceptions for your domains as well.
Additionally, you should never ship code that uses the DisabledTrustEvaluator
, as it would allow all invalid TLS connections.
Alamofire tests include self-signed cert?
The majority of the certificates that exist in the Alamofire test suite are actually self-signed certs. It works exactly as you would expect.
All the data task tests that are written can easily be converted to download task tests by switching the name and providing a destination
parameter. This will download the data into a temporary file instead of reading it into memory. Otherwise they're more or less the same operation.
Additionally, all server trust challenges are handled by the same ServerTrustPolicy
. Data
, Download
and Upload
requests are all handled in the same way.
Best of luck.
Secure connection can't be made
You need to change NSExceptionAllowsInsecureHTTPLoads
to YES
.
NSExceptionAllowsInsecureHTTPLoads
Set the value for this key to YES to allow insecure HTTP loads for the given domain, or to be able
to loosen the server trust evaluation requirements for HTTPS
connections to the domain, as described in Performing Manual Server
Trust Authentication.
How to Connect localhost (with invalid certificate) using Alamofire?
You can easily override the default challenge behavior in Alamofire using the SessionDelegate
override closures. Here is an example of how you can allow Alamofire to accept invalid certificates:
IMPORTANT: Please do not use this in any production code. Security is VERY important and this implementation completely disregards the security mechanisms in Alamofire. Use at your own risk!
let manager = Alamofire.Manager.sharedInstance
manager.delegate.sessionDidReceiveChallenge = { session, challenge in
var disposition: NSURLSessionAuthChallengeDisposition = .PerformDefaultHandling
var credential: NSURLCredential?
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
disposition = NSURLSessionAuthChallengeDisposition.UseCredential
credential = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust)
} else {
if challenge.previousFailureCount > 0 {
disposition = .CancelAuthenticationChallenge
} else {
credential = manager.session.configuration.URLCredentialStorage?.defaultCredentialForProtectionSpace(challenge.protectionSpace)
if credential != nil {
disposition = .UseCredential
}
}
}
return (disposition, credential)
}
We (the Alamofire TC) are going to implement TLS pinning and several other features related to security in the Alamofire 1.3.0 release.
UPDATE
The Alamofire 1.3.0 release is out and adds MUCH better support for customizing server trust authentication challenges. For further info, please check out the Security section of the README.
Related Topics
Dynamic Row Hight Containing Texteditor Inside a List in Swiftui
Intrinsiccontentsize() - Method Does Not Override Any Method from Its Superclass
Array of Nested Type: Why Does the Compiler Complain
What Is Preventing My Conversion from String to Int When Decoding Using Swift 4's Codable
How to Return Value from Async Block in Swift
Swift Nspredicate Throwing Exc_Bad_Access(Code=1, Address=0X1) When Compounding Statements
How to Dispatch Functions in Swift the Right Way
Is There a Prefix Header (Or Something with This Functionality) in Swift
How to Make an Array of the Current Week Dates Swift
How to Generate Large, Ranged Random Numbers in Swift
Swift 2.0: Protocol Extensions: Two Protocols with the Same Function Signature Compile Error
Nsimage to Nsdata as Png Swift
How to Clear the Terminal Screen in Swift
Try, Try! & Try? What's the Difference, and When to Use Each
Manage Ifaddrs to Return MAC Addresses as Well in Swift
Concatenate Two Audio Files in Swift and Play Them