Ios 如何在Objective-C或Swift上发送带有.p12证书的https请求
我有一个react本机项目,我必须使用.p12认证为https请求创建本机模块,但我从未使用Objective-C(有点复杂)或Swift 我找到了一个具有证书的https请求类,但我没有使用该类,因为我没有.h文件和项目文件夹 MyBridge.hIos 如何在Objective-C或Swift上发送带有.p12证书的https请求,ios,objective-c,swift,react-native,react-native-bridge,Ios,Objective C,Swift,React Native,React Native Bridge,我有一个react本机项目,我必须使用.p12认证为https请求创建本机模块,但我从未使用Objective-C(有点复杂)或Swift 我找到了一个具有证书的https请求类,但我没有使用该类,因为我没有.h文件和项目文件夹 MyBridge.h #import "React/RCTBridgeModule.h" @interface MyFirstBridge : NSObject <RCTBridgeModule> @end #导入“React/RCTBridgeMod
#import "React/RCTBridgeModule.h"
@interface MyFirstBridge : NSObject <RCTBridgeModule>
@end
#导入“React/RCTBridgeModule.h”
@接口MyFirstBridge:NSObject
@结束
MyBridge.m
#import "MyFirstBridge.h"
#import <React/RCTLog.h>
@implementation MyFirstBridge
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(sendGetRequest:(NSString *)urllocation:(NSString *)location)
{
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setHTTPMethod:@"GET"];
[request setURL:[NSURL URLWithString:url]];
NSError *error = nil;
NSHTTPURLResponse *responseCode = nil;
NSData *oResponseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&responseCode error:&error];
if([responseCode statusCode] != 200){
NSLog(@"Error getting %@, HTTP status code %i", url, [responseCode statusCode]);
return nil;
}
callback(@[[NSNull null], [[NSString alloc] initWithData:oResponseData encoding:NSUTF8StringEncoding]]);
}
@end
#导入“MyFirstBridge.h”
#进口
@实现MyFirstBridge
RCT_导出_模块();
RCT\u导出\u方法(sendGetRequest:(NSString*)urllocation:(NSString*)位置)
{
NSMutableURLRequest*请求=[[NSMutableURLRequest alloc]init];
[请求设置HttpMethod:@“获取”];
[请求设置url:[NSURL URLWithString:url]];
n错误*错误=nil;
NSHTTPURLResponse*responseCode=nil;
NSData*OresponseStata=[NSURLConnection sendSynchronousRequest:request ReturnInResponse:&responseCode错误:&error];
如果([responseCode statusCode]!=200){
NSLog(@“获取%@时出错,HTTP状态代码%i”,url[responseCode statusCode]);
返回零;
}
回调(@[[NSNull null],[NSString alloc]initWithData:ORESPONTA encoding:NSUTF8StringEncoding]];
}
@结束
它作为基本的
HTTP
get请求工作,但当我尝试https服务时,我需要为每个请求固定一个证书。我如何发送此案例的HTTPS
请求?由于时间不够,我在swift中有此请求,我现在无法将其转换为objective-C,希望您自己转换,
设置请求时也设置URL会话委托
fileprivate func SSLCertificateCreateTrustResult(_ serverTrust: SecTrust)->SecTrustResultType {
let certificate: SecCertificate = SecTrustGetCertificateAtIndex(serverTrust, 0)!
let remoteCertificateData = CFBridgingRetain(SecCertificateCopyData(certificate))!
var certName = "localServerCert"
if serverUrl.contains(find: "uniqueNameinURL"){
certName = "liveServerCert"
}
let cerPath: String = Bundle.main.path(forResource: certName, ofType: "der")!
let localCertificateData = NSData(contentsOfFile:cerPath)!
let certDataRef = localCertificateData as CFData
let cert = (SecCertificateCreateWithData(nil, certDataRef))
let certArrayRef = [cert] as CFArray
SecTrustSetAnchorCertificates(serverTrust, certArrayRef)
SecTrustSetAnchorCertificatesOnly(serverTrust, false)
let trustResult: SecTrustResultType = SecTrustResultType.invalid
return trustResult
}
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
if challenge.protectionSpace.authenticationMethod == (NSURLAuthenticationMethodServerTrust) {
let serverTrust:SecTrust = challenge.protectionSpace.serverTrust!
var localCertificateTrust = SSLCertificateCreateTrustResult(serverTrust)
SecTrustEvaluate(serverTrust, &localCertificateTrust)
if localCertificateTrust == SecTrustResultType.unspecified || localCertificateTrust == SecTrustResultType.proceed
{
let credential:URLCredential = URLCredential(trust: serverTrust)
challenge.sender?.use(credential, for: challenge)
completionHandler(URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
} else {
let properties = SecTrustCopyProperties(serverTrust)
completionHandler(URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil)
}
}
else
{
completionHandler(URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil);
}
}
或您可以遵循以下URL
我猜通过使用.p12证书,您指的是在客户端和服务器之间建立相互身份验证。基本上,您必须完成以下步骤(目标c):
- 创建验证服务器(根据根CA签名验证其签名)和验证客户端(向服务器提供客户端证书以验证其签名)所需的安全对象。加载CA的.cer文件和客户端的.p12文件
- 定义要检索和创建NSURLConnection的URL资源
- 指定要处理的身份验证方法(使用NSURLConnectionLegate回调)
- 处理身份验证挑战(使用NSURLConnectionLegate回调)
NSData *rootCertData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@”rootCert” ofType:@”cer”]];
SecCertificateRef rootCertRef = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef) rootCertData);
NSData *p12Data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@“clientCert" ofType:@"p12"]];
NSArray *item = nil;
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:@“password", kSecImportExportPassphrase, nil];
SecPKCS12Import((CFDataRef) p12Data , (CFDictionaryRef)dict, (CFArrayRef *)item);
SecIdentityRef identity = (SecIdentityRef)[[item objectAtIndex:0] objectForKey:(id)kSecImportItemIdentity];
配置URL(您已经这样做了)
创建NSURLConnection>将必须实现NSURLConnectionLegate才能进行客户身份验证的委托设置为self
// Create url connection and fire request asynchronously
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
在callback CanAuthenticationAgainstProtectionSpace中启用服务器和客户端身份验证
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
if([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust])
return YES;
if([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodClientCertificate])
return YES;
return NO;
}
执行服务器请求的相互身份验证
-(void) connection:didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
//Authenticate the server
if([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust]) { // Verify method
SecTrustRef trust = [[challenge protectionSpace] serverTrust]; // Create trust object
NSArray *trustArray = [NSArray arrayWithObjects:rootCertRef, nil]; // Add as many certificates as needed
SecTrustSetAnchorCertificates(trust, (CFArrayRef) trustArray ); // Set trust anchors
SecTrustResultType trustResult; // Store trust result in this
SecTrustEvaluate(trust, trustResult); // Evaluate server trust
if(trust_result == kSecTrustResultUnspecified) {
NSURLCredential *credential = [NSURLCredential credentialForTrust:trust];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
} else {
// handle error;
}
//Send client identity to server for client authentication
if([[challenge protectionSpace] authenticationMethod] isEqualToString:NSURLAuthenticationMethodClientCertificate]) {
NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity certificates:nil persistence:NSURLCredentialPersistenceNone];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
}
}
你检查了吗?是的,我检查了@Dhruv,但它不起作用。我的另一个问题是为什么不在react native中使用上述库和代码?为什么要编写本机代码?因为我需要编写客户端认证。试着用
-(void) connection:didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
//Authenticate the server
if([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust]) { // Verify method
SecTrustRef trust = [[challenge protectionSpace] serverTrust]; // Create trust object
NSArray *trustArray = [NSArray arrayWithObjects:rootCertRef, nil]; // Add as many certificates as needed
SecTrustSetAnchorCertificates(trust, (CFArrayRef) trustArray ); // Set trust anchors
SecTrustResultType trustResult; // Store trust result in this
SecTrustEvaluate(trust, trustResult); // Evaluate server trust
if(trust_result == kSecTrustResultUnspecified) {
NSURLCredential *credential = [NSURLCredential credentialForTrust:trust];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
} else {
// handle error;
}
//Send client identity to server for client authentication
if([[challenge protectionSpace] authenticationMethod] isEqualToString:NSURLAuthenticationMethodClientCertificate]) {
NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity certificates:nil persistence:NSURLCredentialPersistenceNone];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
}
}