目前我正在使用ios中的XMPP
协议进行聊天应用。我想在登录按钮上放置警报视图和身份验证。如果验证成功,那么用户可以看到主屏幕屏幕,否则会出现警报视图请检查用户名和密码我显示聊天安全开源项目但我无法理解。
//appdelegate.m file .//
- (BOOL)connect
{
if (![xmppStream isDisconnected]) {
return YES;
// isauthenticate=YES;
}
NSString *myJID = [[NSUserDefaults standardUserDefaults] stringForKey:kXMPPmyJID];
NSString *myPassword = [[NSUserDefaults standardUserDefaults] stringForKey:kXMPPmyPassword];
//
// If you don't want to use the Settings view to set the JID,
// uncomment the section below to hard code a JID and password.
//
// myJID = @"user@gmail.com/xmppframework";
// myPassword = @"";
if (myJID == nil || myPassword == nil) {
return NO;
}
[xmppStream setMyJID:[XMPPJID jidWithString:myJID]];
password = myPassword;
NSError *error = nil;
if (![xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&error])
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error connecting"
message:@"See console for error details."
delegate:nil
cancelButtonTitle:@"Ok"
otherButtonTitles:nil];
[alertView show];
DDLogError(@"Error connecting: %@", error);
return NO;
}
return YES;
}
- (void)disconnect
{
[self goOffline];
[xmppStream disconnect];
}
#pragma mark UIApplicationDelegate
- (void)applicationDidEnterBackground:(UIApplication *)application
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
#if TARGET_IPHONE_SIMULATOR
DDLogError(@"The iPhone simulator does not process background network traffic. "
@"Inbound traffic is queued until the keepAliveTimeout:handler: fires.");
#endif
if ([application respondsToSelector:@selector(setKeepAliveTimeout:handler:)])
{
[application setKeepAliveTimeout:600 handler:^{
DDLogVerbose(@"KeepAliveHandler");
// Do other keep alive stuff here.
}];
}
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
}
- (void)applicationWillTerminate:(UIApplication *)application
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
[self teardownStream];
}
#pragma mark XMPPStream Delegate
- (void)xmppStream:(XMPPStream *)sender socketDidConnect:(GCDAsyncSocket *)socket
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
}
- (void)xmppStream:(XMPPStream *)sender willSecureWithSettings:(NSMutableDictionary *)settings
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
NSString *expectedCertName = [xmppStream.myJID domain];
if (expectedCertName)
{
settings[(NSString *) kCFStreamSSLPeerName] = expectedCertName;
}
if (customCertEvaluation)
{
settings[GCDAsyncSocketManuallyEvaluateTrust] = @(YES);
}
}
- (void)xmppStream:(XMPPStream *)sender didReceiveTrust:(SecTrustRef)trust
completionHandler:(void (^)(BOOL shouldTrustPeer))completionHandler
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
// The delegate method should likely have code similar to this,
// but will presumably perform some extra security code stuff.
// For example, allowing a specific self-signed certificate that is known to the app.
dispatch_queue_t bgQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(bgQueue, ^{
SecTrustResultType result = kSecTrustResultDeny;
OSStatus status = SecTrustEvaluate(trust, &result);
if (status == noErr && (result == kSecTrustResultProceed || result == kSecTrustResultUnspecified)) {
completionHandler(YES);
}
else {
completionHandler(NO);
}
});
}
- (void)xmppStreamDidSecure:(XMPPStream *)sender
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
}
- (void)xmppStreamDidConnect:(XMPPStream *)sender
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
isXmppConnected = YES;
NSError *error = nil;
if (![[self xmppStream] authenticateWithPassword:password error:&error])
{
DDLogError(@"Error authenticating: %@", error);
}
}
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
{
isauthenticate=YES;
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
[self goOnline];
}
- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(NSXMLElement *)error
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
}
我尝试在BOOL(isauthenticate)
方法中设置xmppStreamDidAuthenticate
但未成功。我可以重定向到主页,但如果我写错了细节仍然会重定向到主页。如果用户名或密码错误并且未通过服务器进行身份验证,我想设置它。
//view controller.m file //
#import "ViewController.h"
#import "AppDelegate.h"
@interface ViewController ()<MBProgressHUDDelegate>
{
MBProgressHUD *HUD;
IBOutlet UITextField *mViewEmail;
IBOutlet UITextField *mViewPassword;
}
@end
NSString *const kXMPPmyJID = @"kXMPPmyJID";
NSString *const kXMPPmyPassword = @"kXMPPmyPassword";
@implementation ViewController
- (IBAction)checkLogin:(id)sender {
NSLog(@"Email: %@ Password: %@",mViewEmail.text,mViewPassword.text);
[self setField:mViewEmail forKey:kXMPPmyJID];
[self setField:mViewPassword forKey:kXMPPmyPassword];
// if (appdelegate.connect==YES) {
if([ [self appDelegate] connect]) {
// if (appdelegate.isauthenticate==YES) {
HUD = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES] ;
HUD.delegate = self;
HUD.color = [UIColor blackColor];
HUD.labelText = @"Please Wait";
HUD.dimBackground = YES;
// HUD.detailsLabelText = @"Close chat";
[self showHome];
//}
}
//}
else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Sorry"
message:@"Please Check Username or Password"
delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
}
}
- (void)showHome{
[self performSegueWithIdentifier:@"signIn" sender:self];
}
答案 0 :(得分:3)
确定。最后我的问题解决了。我发布了我的答案。首先我的错误是我忘了写
appdelegate = (AppDelegate*)[[UIApplication sharedApplication]delegate];
appdelegate.viewController = self; // very imp when you call method in app delegate.h
在我的视图控制器中。因此,当我在appdelegate中调用viewcontroller方法时,它会调用但由于缺少上述方法而无法执行(第二行)。然后我在 - (void)xmppStreamDidAuthenticate:(XMPPStream *)sender 方法中调用了view controller的segue方法。然后完美地工作。所以我的最终解决方案是
//app delegate.m file//
- (BOOL)connect
{
// Setup HUD(Activity Indicator) when Connect method call //
HUD = [[MBProgressHUD alloc] initWithWindow:[UIApplication sharedApplication].keyWindow]; [self.window.rootViewController.view addSubview:HUD];
[HUD setDetailsLabelText:@"Please wait..."];
[HUD setDimBackground:YES];
[HUD setOpacity:0.5f];
[HUD show:YES];
if (![xmppStream isDisconnected]) {
return YES;
}
NSString *myJID = [[NSUserDefaults standardUserDefaults] stringForKey:kXMPPmyJID];
NSString *myPassword = [[NSUserDefaults standardUserDefaults] stringForKey:kXMPPmyPassword];
if (myJID == nil || myPassword == nil) {
return NO;
}
[xmppStream setMyJID:[XMPPJID jidWithString:myJID]];
password = myPassword;
NSError *error = nil;
if (![xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&error])
{
HUD.hidden=YES;
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error connecting"
message:@"See console for error details."
delegate:nil
cancelButtonTitle:@"Ok"
otherButtonTitles:nil];
[alertView show];
DDLogError(@"Error connecting: %@", error);
return NO;
}
return YES;
}
- (void)disconnect
{
[self goOffline];
[xmppStream disconnect];
}
#pragma mark UIApplicationDelegate
- (void)applicationDidEnterBackground:(UIApplication *)application
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
#if TARGET_IPHONE_SIMULATOR
DDLogError(@"The iPhone simulator does not process background network traffic. "
@"Inbound traffic is queued until the keepAliveTimeout:handler: fires.");
#endif
if ([application respondsToSelector:@selector(setKeepAliveTimeout:handler:)])
{
[application setKeepAliveTimeout:600 handler:^{
DDLogVerbose(@"KeepAliveHandler");
// Do other keep alive stuff here.
}];
}
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
}
- (void)applicationWillTerminate:(UIApplication *)application
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
[self teardownStream];
}
#pragma mark XMPPStream Delegate
- (void)xmppStream:(XMPPStream *)sender socketDidConnect:(GCDAsyncSocket *)socket
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
}
- (void)xmppStream:(XMPPStream *)sender willSecureWithSettings:(NSMutableDictionary *)settings
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
NSString *expectedCertName = [xmppStream.myJID domain];
if (expectedCertName)
{
settings[(NSString *) kCFStreamSSLPeerName] = expectedCertName;
}
if (customCertEvaluation)
{
settings[GCDAsyncSocketManuallyEvaluateTrust] = @(YES);
}
}
- (void)xmppStream:(XMPPStream *)sender didReceiveTrust:(SecTrustRef)trust
completionHandler:(void (^)(BOOL shouldTrustPeer))completionHandler
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
dispatch_queue_t bgQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(bgQueue, ^{
SecTrustResultType result = kSecTrustResultDeny;
OSStatus status = SecTrustEvaluate(trust, &result);
if (status == noErr && (result == kSecTrustResultProceed || result == kSecTrustResultUnspecified)) {
completionHandler(YES);
}
else {
completionHandler(NO);
}
});
}
- (void)xmppStreamDidSecure:(XMPPStream *)sender
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
}
- (void)xmppStreamDidConnect:(XMPPStream *)sender
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
isXmppConnected = YES;
NSError *error = nil;
if (![[self xmppStream] authenticateWithPassword:password error:&error])
{
DDLogError(@"Error authenticating: %@", error);
}
}
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
{
HUD.hidden=YES; //Hud Will be hide when User Authenticated
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
[self.viewController showHome]; // view controllers method to go to next view controller //
[self goOnline];
}
- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(NSXMLElement *)error
{
// HUD will be hidden and alertview will be shown //
HUD.hidden=YES;
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Sorry"
message:@"Please Check Username or Password"
delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
isauthenticate=NO;
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
{
NSLog(@"error = %@", error);
}
}
并在viewcontroller.m中我们已经表明viewcontroller也是appdelegate控制器。所以我们必须在 - (void)viewDidLoad 方法中声明它。
// viewcontroller.m file//
- (void)viewDidLoad
{
[super viewDidLoad];
appdelegate = (AppDelegate*)[[UIApplication sharedApplication]delegate];
appdelegate.viewController = self;
}
- (AppDelegate *)appDelegate
{
return (AppDelegate *)[[UIApplication sharedApplication] delegate];
}
- (IBAction)checkLogin:(id)sender {
[self dismissKeyboard];
NSLog(@"Email: %@ Password: %@",mViewEmail.text,mViewPassword.text);
[self setField:mViewEmail forKey:kXMPPmyJID];
[self setField:mViewPassword forKey:kXMPPmyPassword];
[[self appDelegate ]connect];//call when loginbutton pressed
}
//call in appdelegate.h // segue(push) to next view
- (void)showHome
{
[self performSegueWithIdentifier:@"signIn" sender:self];
}
注意:我尽可能多地解释。
答案 1 :(得分:1)
如果用户名和密码正确,那么xmppStreamDidAuthenticate方法调用,如果其中一个不正确,那么didNotAuthenticate方法调用。
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
{
}
- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(NSXMLElement *)error
{
NSLog(@"error = %@", error);
}
此处打印错误并根据需要在UIALertview中显示此错误。
答案 2 :(得分:0)
实际上,您正在检查XMPP
连接并非Authenticate User
。如果用户名和密码正确无误,则表示您已收到xmppStreamDidAuthenticate
方法的回复。在验证用户后,您可以编写代码以推送到HomeViewController。
在以下两种方法中,您可以在用户变更后显示警报或推送到另一个视图。
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
{
}
- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(NSXMLElement *)error
{
NSLog(@"Error");
}
这是XMPP
委托方法
希望这对你有所帮助。