【问题标题】:How to prevent the extra view displaying an access code when using Google OAuth 2.0使用 Google OAuth 2.0 时如何防止显示访问代码的额外视图
【发布时间】:2011-11-25 08:32:02
【问题描述】:

我关注了http://googlemac.blogspot.com/2011/05/ios-and-mac-sign-in-controllers.html,以允许用户使用 Google 登录 iPhone 应用。在我点击“允许访问”按钮后,我得到一个额外的屏幕,上面写着:“请复制此代码,切换到您的应用程序并将其粘贴到那里:(文本框中的代码)。”

这就是我所拥有的:

- (IBAction)googleLoginTapped:(UIButton *)sender
{
    [self loginToGoogle];
}

- (void)loginToGoogle 
{

    // For Google APIs, the scope strings are available
    // in the service constant header files.
    NSString *scope =@"https://www.googleapis.com/auth/userinfo.profile";

    // Typically, applications will hardcode the client ID and client secret
    // strings into the source code; they should not be user-editable or visible.

    // But for this sample code, they are editable.
    NSString *clientID = @"my clientID";
    NSString *clientSecret = @"my clientSecret";


    // Display the autentication view.
    SEL finishedSel = @selector(viewController:finishedWithAuth:error:);

    GTMOAuth2ViewControllerTouch *viewController;

    viewController = [GTMOAuth2ViewControllerTouch controllerWithScope:scope
                                                              clientID:clientID
                                                          clientSecret:clientSecret
                                                      keychainItemName:nil
                                                              delegate:self
                                                      finishedSelector:finishedSel];

    // For this sample, we'll force English as the display language.
    NSDictionary *params = [NSDictionary dictionaryWithObject:@"en"
                                                       forKey:@"hl"];

    viewController.signIn.additionalAuthorizationParameters = params;

    // Optional: display some html briefly before the sign-in page loads
    NSString *html = @"<html><body bgcolor=silver><div align=center>Loading sign-in page...</div></body></html>";
    viewController.initialHTMLString = html;

    viewController.signIn.shouldFetchGoogleUserProfile = YES;

    [self presentModalViewController:viewController animated:YES];
}

- (void)viewController:(GTMOAuth2ViewControllerTouch *)viewController finishedWithAuth:(GTMOAuth2Authentication *)auth error:(NSError *)error
{
    if (error != nil) 
    {
        // Authentication failed (perhaps the user denied 

请看这个链接,这很好https://developers.google.com/accounts/docs/OAuth2InstalledApp

【问题讨论】:

  • @kevlar 有正确答案

标签: ios oauth-2.0


【解决方案1】:

我试过这种方法,效果很好,把它放在你的 webViewDidFinishLoad 方法中:

if ([webView.request.URL.absoluteString rangeOfString:@"https://accounts.google.com/o/oauth2/approval?"].location != NSNotFound) {
    webView.hidden=YES;
}

【讨论】:

  • 澄清一下:您需要将以上行复制并粘贴到 Google API Objective C 客户端库的 OAuth2 部分中的文件 GTMOAuth2ViewControllerTouch.m 中。这是一个 hack,但它对我有用。
  • 谢谢!这是唯一对我有用的解决方案。
  • 我也做了同样的事情,但无法隐藏 webview。即使按照上述条件隐藏它仍然可以看到。我也确定了断点。
【解决方案2】:

我找到了答案。最初,我将客户端 ID 用于已安装的应用程序。这没有提供设置重定向 URI 的选项。它给出了默认的重定向 URI urn:ietf:wg:oauth:2.0:oob http://localhost 所以当我使用此代码发送身份验证请求时:

viewController = [GTMOAuth2ViewControllerTouch controllerWithScope:scope
                                                              clientID:clientID
                                                          clientSecret:clientSecret
                                                      keychainItemName:nil
                                                              delegate:self
                                                      finishedSelector:finishedSel];

它返回一个成功代码,然后用于授权本机应用程序。有关返回代码或令牌的更多信息,请参考here

为了解决我的问题,我继续使用 Web 应用程序的客户端 ID。这允许我显式设置重定向 URI,还允许我将 response_type 设置为令牌而不是此处的代码:

https://accounts.google.com/o/oauth2/auth?
  client_id=21302922996.apps.googleusercontent.com&
  redirect_uri=https://www.example.com/back&
  scope=https://www.google.com/m8/feeds/&
  response_type=**token**

因此,当我通过身份验证并从服务器返回 redirect_uri 时,它附带一个“access_token”作为查询字符串附加,如下所示:

https://www.example.com/back?access_token=returned_access_tocken

现在你可以使用正则表达式代码了:

-(void)checkForAccessToken:(NSString *)urlString {
    NSError *error;
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"access_token=(.*)&" options:0 error:&error];
    if (regex != nil) 
    {
        NSTextCheckingResult *firstMatch = [regex firstMatchInString:urlString options:0 range:NSMakeRange(0, [urlString length])];
        if (firstMatch) 
        {
            NSRange accessTokenRange = [firstMatch rangeAtIndex:1];
            NSString *accessToken = [urlString substringWithRange:accessTokenRange];
            accessToken = [accessToken stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
            [_delegate accessTokenFoundGoogle:accessToken];
            accessTokenFound = YES;
        }
    }
}

在此处提取 access_code 并将其用于您的授权请求:

"https://www.googleapis.com/oauth2/v1/userinfo?oauth_token=put_your_accesstoken_here" to send a request for authorization

然后您可以发送您的请求并在这种情况下以 JSON 格式取回用户的个人资料信息。你可以参考这个question and answer使用Facebook的graph api来登录用户。然后只需使用我在此处包含的建议和请求 url 修改代码以使用新的 Google OAuth 2.0。只是在为 Facebook 转换代码时为您加快速度的建议,创建一个新的 init 方法,如下所示:

- (id)initWithDelegate:(id<GoogleLoginDialogDelegate>)delegate;

- (id)initWithDelegate:(id<GoogleLoginDialogDelegate>)delegate 
{
    if ((self = [super initWithNibName:@"GoogleLoginDialog" bundle:[NSBundle mainBundle]])) {
        self.delegate = delegate;
    }
    return self;    
}

这样您就可以轻松地使用 Google 登录对话框中的委托方法。如果您仔细按照 Facebook 示例进行操作,您应该使用 OAuth 进行 Google 登录!

【讨论】:

  • 我们如何使用这个告诉我 400。这是一个错误。错误:invalid_request 缺少必需参数:response_type
【解决方案3】:

事实证明这很简单。在登录回调中,只需从父视图控制器中关闭并删除 viewController

- (void)viewController:(UIViewController *)viewController
      finishedWithAuth:(GTMOAuth2Authentication *)auth
                 error:(NSError *)error
{
    if (error == nil) {
        // Get rid of the login view.
        // self.parentViewController was saved somewhere else and is the parent
        // view controller of the view controller that shows the google login view.
        [self.parentViewController dismissViewControllerAnimated:NO completion:nil];
        [viewController removeFromParentViewController];

        // Tell the delegate that the user successfully logged in ...
    } else {
        // Error handling code ...
    }
}

【讨论】:

  • 这对我不起作用——“请复制此代码”消息的闪烁调用 viewController:finishedWithAuth:error: 之前发生.
  • 在 iPhone、iOS 9.2.1 (Swift) 上为我工作。虽然它并不完美。用户仍然可以短暂地看到“请复制此代码...”屏幕。我会继续寻找更好的解决方案。
【解决方案4】:

我通过将视图控制器嵌套在 UINavigationController 中来解决此问题。不知道为什么这样做会成功,但确实如此。

所以不是

[self presentModalViewController:viewController animated:YES];

...使用

UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
[self presentModalViewController:navigationController animated:YES];

【讨论】:

    【解决方案5】:

    使用 gtm-oauth2 登录 Google 服务时,请确保 Google API Console 项目注册在 API 访问部分中显示客户端 ID 是为已安装应用程序颁发的。这在 gtm-oauth2 documentation 中有描述。

    【讨论】:

      【解决方案6】:

      在创建客户端 ID 时,选择 web 应用程序而不是已安装的应用程序,这将解决您的问题。

      编码愉快 :)

      【讨论】:

        【解决方案7】:

        我试过这个技巧,它成功了......

        GTMOAuth2ViewControllerTouch.h 中的以下方法替换 webview shouldStartLoadWithRequest。它不会显示验证码页面。

        *- (BOOL)webView:(UIWebView *)webView
          shouldStartLoadWithRequest:(NSURLRequest *)request
                      navigationType:(UIWebViewNavigationType)navigationType {
            if (!hasDoneFinalRedirect_)
            {
                hasDoneFinalRedirect_ = [signIn_ requestRedirectedToRequest:request];
        
                if ([request.URL.absoluteString rangeOfString:@"https://accounts.google.com/o/oauth2/approval?"].location != NSNotFound)
                {
                    self.redirectView.frame=[UIScreen mainScreen].bounds;
                    //webView.frame=[UIScreen mainScreen].bounds;
                    [self.activityView startAnimating];
                    [webView addSubview:self.redirectView];
        
                    return YES;
                }
                else if(hasDoneFinalRedirect_) {
                    // signIn has told the view to close
                    return NO;
                }
            }
        
            return YES;
        }*
        

        在此我通过检查此批准 url https://accounts.google.com/o/oauth2/approval? 将我自己的自定义视图 (redirectView) 添加到此身份验证页面

        您还应该在 GTMOAuth2ViewControllerTouch 的 xib 中添加 activityView 以在重定向回应用程序时显示加载程序。

        【讨论】:

          【解决方案8】:

          经过至少 20 个小时的配置,我终于开始运行了。我之前还将我的 swift 文件导入到我的 GTMOAuth2ViewControllerTouch.m 文件中。不确定这是否会影响它,但我补充说:

              #import "myBundleId-Swift.h"
          

          然后,我需要在 viewController.swift 文件中添加最后两行:

           // Handle completion of the authorization process, and updates the Drive service
          // with the new credentials.
          func viewController(viewController: GTMOAuth2ViewControllerTouch , finishedWithAuth authResult: GTMOAuth2Authentication, error:NSError? ) {
              if let error = error
              {
                  self.showAlert("Authentication Error", message:error.localizedDescription)
                  self.driveService.authorizer = nil
              } else {
                  print("Authentication success")
                  self.driveService.authorizer = authResult
          //This where we need to get rid of the copy the code screen:
                  self.parentViewController?.dismissViewControllerAnimated(false, completion:nil)
                  viewController.removeFromParentViewController()
              }
          }
          

          这摆脱了复制此代码屏幕。

          【讨论】:

            猜你喜欢
            • 2015-11-11
            • 2015-09-26
            • 1970-01-01
            • 2012-03-06
            • 2017-10-19
            • 1970-01-01
            • 2015-10-02
            • 2017-08-06
            • 1970-01-01
            相关资源
            最近更新 更多