在 Objective-C 中使用身份验证获取 JSON 令牌
Posted
技术标签:
【中文标题】在 Objective-C 中使用身份验证获取 JSON 令牌【英文标题】:Obtaining an JSON Token using Authentication in Objective-C 【发布时间】:2018-02-08 13:28:15 【问题描述】:您好,ios 新手只是尝试将应用程序连接到 API 并使用身份验证获取我的令牌。我尝试了很多不同的选择,但似乎无法理解它。我要做的就是获得我的令牌。谁能看到我哪里出错了? API 文档在这里:https://simplybook.me/en/api/developer-api
NSURL *url = [NSURL URLWithString:@"http://user-api.simplybook.me/login/"];
NSURLSession *session = [NSURLSession sharedSession];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"myloginname" forHTTPHeaderField:@"X-Company-Login"];
[request setValue:@"mytokenhere" forHTTPHeaderField:@"X-Token"];
NSURLSessionDataTask *downloadTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
if (!error)
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSArray * resultDict =[json objectForKey:@"name"];
NSLog(@"%@", resultDict);
else
NSLog(@"%@", error);
];
[downloadTask resume];
【问题讨论】:
您是否尝试过在 api url 中使用https
而不是 http
?此外,downloadTask
是否已执行,或者您在触发请求时是否收到任何错误?
现在使用 https 还是同样的问题。 downloadTask 没有错误
【参考方案1】:
不要像这样声明NSURLSession
:
NSURLSession *session = [NSURLSession sharedSession];
试试这个:
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
NSURL *url = [NSURL URLWithString:@"https://user-api.simplybook.me/login/"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
此外,请确保您已在头文件中声明了 NSURLSessionDelegate
协议。
【讨论】:
我试过这个没有运气。会议工作正常。它只是使用标题来尝试获取我卡住的访问令牌。 @user7322261 好的,抱歉,我认为这可能是与sharedSession
相关的问题;您可以尝试的最后一件事,将自定义标题切换到 addValue
而不是 setValue
还是不行,谢谢!你知道 API 文档中我的 HTTP 标头字段应该是什么吗?
@user7322261 我快速浏览了文档,您设置的 2 个标题似乎是正确的。您也可以尝试将这个添加到请求中:[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
啊,我刚刚注意到上面我写的 mytokenhere 行实际上是 API 密钥。我只是想获得我实际上还没有的令牌。在他们使用的文档中 var token = loginClient.getToken(YOUR_COMPANY_LOGIN, YOUR_API_KEY);【参考方案2】:
我会给你获取令牌的示例代码,但这是关于访问和刷新令牌的。你现在可以很清楚地理解它了。
ViewController.m
- (void)viewDidLoad
[super viewDidLoad];
- (IBAction)actionLogin:(id)sender
[self loginForGettingAccessandRefreshToken];
-(void)loginForGettingAccessandRefreshToken
@try
NSString *strUserName = [textUsername.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSString *strPassword = [textPassword.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSString *strParameters = [NSString stringWithFormat:@"client_id=roclient&client_secret=secret&grant_type=password&username=%@&password=%@&scope=dataEventRecords offline_access", strUserName, strPassword];
id param = strParameters;
NSLog(@"The param is - %@",param);
[GlobalShareClass postLoginDataToServer:BASEURL_LOGIN passParameters:param success:^(id res)
if([res isKindOfClass:[NSDictionary class]])
NSDictionary *dictRes = [res copy];
NSString *strErrDesc = [NSString stringWithFormat:@"%@",[dictRes objectForKey:@"error_description"]];
if([[dictRes allKeys] containsObject:@"error_description"])
dispatch_async(dispatch_get_main_queue(), ^
//Dispaly UI
);
else
NSString *strAccessToken = [dictRes objectForKey:@"access_token"];
NSString *strRefreshToken = [dictRes objectForKey:@"refresh_token"];
NSString *strTokenType = [dictRes objectForKey:@"token_type"];
NSString *sstrExpiresIn = [dictRes objectForKey:@"expires_in"];
[[NSUserDefaults standardUserDefaults] setObject:globalShare.strRefreshToken forKey:@"refresh_token"];
[[NSUserDefaults standardUserDefaults] setObject:globalShare.strAccessToken forKey:@"access_token"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSDictionary *responseDict = [GlobalShareClass getDataFromToken:globalShare.strAccessToken];
NSString *strFetchedSub = [[NSUserDefaults standardUserDefaults] stringForKey:@"loginIdSub"];
globalShare.loginId = [responseDict objectForKey:@"sub"];
else
NSLog(@"The res starts with array");
failure:^(NSError *error)
// error handling here ...
NSLog(@"%@", [error localizedDescription]);
dispatch_async(dispatch_get_main_queue(), ^
//Showing Error
);
passViewController:self];
@catch(NSException *exception)
NSLog(@"%@",[exception description]);
@finally
GlobalShareClass.h
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
@interface GlobalShareClass : NSObject
NSMutableArray *arr;
@property (strong, nonatomic) NSMutableArray *arr;
+ (GlobalShareClass *)sharedInstance;
+ (void)postLoginDataToServer:(NSString *)url passParameters:(id)parameter success:(void (^)(id res))successPost failure:(void(^)(NSError* error))failurePost passViewController:(UIViewController *)vc;
+ (NSDictionary *)getDataFromToken:(NSString *)strToken;
+ (NSDictionary *)urlBase64Decode:(NSString *)strToParse;
@end
GlobalShareClass.m
#import "GlobalShareClass.h"
@implementation GlobalShareClass
@synthesize arr;
+ (GlobalShareClass *)sharedInstance
static GlobalShareClass* _shareInstane = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
_shareInstane = [[GlobalShareClass alloc] init];
//Incase array of initialization
_shareInstane.arr = [[NSMutableArray alloc] init];
);
return _shareInstane;
+ (void)postLoginDataToServer:(NSString *)url passParameters:(id)parameter success:(void (^)(id res))successPost failure:(void(^)(NSError* error))failurePost passViewController:(UIViewController *)vc
GlobalShareClass *globalShare = [GlobalShareClass sharedInstance];
__block id jsonResp;
NSData *data = [parameter dataUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
[request setHTTPMethod:@"POST"];
[request setValue:@"application/x-www-form-urlencoded;charset=UTF-8" forHTTPHeaderField:@"content-type"];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSURLSessionUploadTask *dataTask = [session uploadTaskWithRequest: request
fromData:data completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
if(data == nil && error)
NSLog(@"uploadTaskWithRequest error: %@", error);
failurePost(error);
else
jsonResp = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSString *strStatusCode = [NSString stringWithFormat:@"%ld",(long)[((NSHTTPURLResponse *)response) statusCode]];
if([strStatusCode isEqualToString:@"400"])
successPost(jsonResp);
NSString *strStatusCodeResponse = [self strGetStatusResponseCode:strStatusCode];
if([strStatusCodeResponse length] > 0)
dispatch_async(dispatch_get_main_queue(), ^
// Showing error
);
else
jsonResp = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
if([jsonResp objectForKey:@"error"] || jsonResp == nil)
dispatch_async(dispatch_get_main_queue(), ^
[self showAlertController:@"Error" :[jsonResp objectForKey:@"error_description"] passViewController:vc];
);
else
successPost(jsonResp);
];
[dataTask resume];
+ (NSDictionary *)getDataFromToken:(NSString *)strToken
NSDictionary *data;
NSString *encoded = [strToken componentsSeparatedByString:@"."][1];
data = [GlobalShareClass urlBase64Decode:encoded];
return data;
+ (NSDictionary *)urlBase64Decode:(NSString *)strToParse
@try
NSDictionary *returnDict;
NSString *output = [strToParse stringByReplacingOccurrencesOfString:@"-" withString:@"+"];
output = [output stringByReplacingOccurrencesOfString:@"_" withString:@"/"];
switch (output.length % 4)
case 0:
case 1:
break;
case 2:
output = [output stringByAppendingString:@"=="];
break;
case 3:
output = [output stringByAppendingString:@"="];
break;
default:
break;
NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:output options:0];
NSString *decodedString = [[NSString alloc] initWithData:decodedData encoding:NSUTF8StringEncoding];
NSLog(@"%@", decodedString);
NSData *data = [decodedString dataUsingEncoding:NSUTF8StringEncoding];
returnDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
return returnDict;
@catch (NSException *exception)
NSLog(@"%@", [exception description]);
@end
【讨论】:
以上是关于在 Objective-C 中使用身份验证获取 JSON 令牌的主要内容,如果未能解决你的问题,请参考以下文章
使用 Objective-C 和 C++ 实现 X-FACEBOOK-PLATFORM 身份验证的身份验证失败
从 Objective-C 向 IIS 发送请求时需要身份验证
使用 j_security_check 在 Java EE / JSF 中执行用户身份验证