• ios telegram iOS telegram二次开发


    二次开发方案
    一、方案的确定及要实现的效果
           首先,最多的信息获取还是官方文档:https://lw.microstrategy.com/msdz/MobileUpdates/941_iOSU5/docs/mergedProjects/mobile_sdk/mobilesdk.htm

    在本项目的一小部分,项目需求也是改来改去,最终需要实现的有:

    应用图标的替换,应用名称的更改,启动图片的替换。
    自定义登录界面。
    登录时进行VPN验证,通过VPN服务器实现外网访问。
    动态更改app的显示模式(文件夹目录或者默认报表)。
    服务器集群,负载均衡的使用。


    二、实现步骤
          1、需求一的实现很简单,图标更改在Images.xcassets里面直接替换。应用名称在Info_IPad.plist,Bundle display name对应的名字改掉就可以。

    Home > Mobile SDK > Mobile SDK for iOS > Customizing MicroStrategy Mobile > Customization scenarios > Adding functionality with a custom Application Delegate。    

    //
    //  CustomAppDelegate.m
    //  MicroStrategyMobile
    //
    //  Copyright (c) 2014 MicroStrategy Inc. All rights reserved.
    //

    #import "CustomAppDelegate.h"
    #import "CustomLoginView.h"
    #import
    #import
    #import

    @implementation CustomAppDelegate
    -(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
        BOOL res = [super application:application didFinishLaunchingWithOptions:launchOptions];
        //add custom logic here

        return res;
    }
    @end
     


          创建自定义的登录界面
    Home > Mobile SDK > Mobile SDK for iOS > Customizing authentication > Client-side customizations > Programmatic customizations > Customizing login screen UI and authentication parameters programmatically

    #import "CustomLoginView.h"

    @implementation CustomLoginView

    - (void) setupWithParameters:(NSDictionary*) promptViewParameters delegate:(id) delegate{

        [super setupWithParameters:promptViewParameters delegate:delegate];
        //After calling super, add additional code to setup the login UI, for example, add textfields, login buttons, background image

        
    }

    -(void) login{

        [self.delegate loginPromptView:self didInputAuthenticationParameters:@{

             @"username":([usernameTextField text]?[usernameTextField text]:EMPTY_STRING),

             @"password":([passwordTextField text]?[passwordTextField text]:EMPTY_STRING)

        }];

    }

    @end
     


          同时CustomAppDelegate.m文件也要做更改


    //
    //  CustomAppDelegate.m
    //  MicroStrategyMobile
    //
    //  Copyright (c) 2014 MicroStrategy Inc. All rights reserved.
    //

    #import "CustomAppDelegate.h"
    #import "CustomLoginView.h"
    #import
    #import
    #import
    #import

    @implementation CustomAppDelegate

    -(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{    

        CustomLoginView *loginView = [[CustomLoginView alloc] initWithFrame:self.window.frame];

        MSIAuthenticationPromptViewController *loginViewController = [[MSIAuthenticationPromptViewController alloc] init];

        MSIAuthenticationModule *loginModule = [[MSIAuthenticationModule alloc] init];

        [[MSIMobileLoginManager sharedMobileLoginManager] setView:loginView controller:loginViewController module:loginModule forPromptType:AuthenticationPromptType];

        BOOL res = [super application:application didFinishLaunchingWithOptions:launchOptions];

        return res;
    }

    @end
     


    Home > Mobile SDK > Mobile SDK for iOS > Customizing authentication > Client-side customizations > Programmatic customizations > Adding custom logic during authentication process。

    到此,自定义登录界面已经实现。

        3、VPN服务器的认证和使用

          在iOS平台下,第三方应用程序通过调用移动应用安全认证开发包,使用证书与VPN服务器建立安全通道、以及单点登录等功能的实现。此处以北京国富安提供的开发包为例(具体细节参照国富安提供的开发文档)。

    首先在iPad端安装移动认证证书(国富安提供)。
    从Keychain里读取证书的cn。设置指定CN的证书,用此证书来做为身份。根据身份证书去跟vpn建立ssl连接。
    根据VPN上配置的资源,启动本地监听的端口。
    通过VPN调用服务器接口,获取配置文件。
    显示登录界面,点击登录,根据证书和主账号密码进行统一安全认证。
    认证成功返回的json,包含移动平台用户的主从账号信息,并会在Keychain中存储session,附应用可以通过Keychain中存储的session直接登录成功。
    根据json信息,将主账号作为mstr用户账号和mstr用户默认密码一起,在应用内自动进行mstr的认证。成功界面会跳转,不跳转且无提示可以检查所使用mstr用户是否存在。(注:以移动平台主账号为账号,自定义统一的默认密码,提前在mstr创建用户)
          

    /**
     *  2、从设备的钥匙串中获取证书,如果获取失败就返回nil;
     *  @return 证书或者nil
     */
    -(NSString *)getCNfromKeychain
    {
        NSMutableArray *outArray = [[NSMutableArray alloc] init];
        //获取证书cn项,因为有可能有多个证书,所以返回的是一个cn项的数组
        BOOL ret = [[CertHelper sharedInstance] getCNfromKeychain:outArray];
        if (!ret)
        {
            NSLog(@"获取证书失败,请联系管理员");
            return nil;
        }
        //一般情况只有一个证书
        NSString *certCN = [outArray objectAtIndex:0];
        return certCN;
    }

    if ([[CertHelper sharedInstance] setIndexbyCN:[self getCNfromKeychain]] == -1) //指定身份证书,返回-1表示设置指定证书失败
        {
            NSLog(@"your identity error");
        }

    /**
     * 将身份证书和VPN做认证以登录VPN创建ssl连接
     *  @return VPN连接状态
     */
    -(BOOL)connectVPN
    {
        int iResult = -1;
        @try {
            iResult =[[L4Proxy sharedInstance] L4Proxy_ShakeHands_With_VPN:kVPNServer IPPort:kVPNPort username:@"" password:@""];
        }
        @catch (NSException *exception) {
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"网络连接失败" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
            [alertView show];
            return NO;
        }
        @finally {
            if (iResult != 0) {
                NSLog(@"VPN 登录失败");
                return NO;
            }else {
                NSLog(@"VPN 登录成功");
                return YES;
            }
        }
    }
     


    // 3、获取监听端口
    - (void)refreshConnectionInfo
    {
        Constants* constants = [Constants sharedInstance];
        int webPort = [[L4Proxy sharedInstance] startLocalListen:@"BI-8080"];
        int port = [[L4Proxy sharedInstance] startLocalListen:@"BI-34952"];
        
        if(webPort > 0) {
            constants.webPort = webPort;
            constants.webServer = LOCAL_HOST;
        }
        
        if(port > 0) {
            constants.port = port;
            constants.iserver = LOCAL_HOST;
        }
    }
     


    /*
        5、6、点击登陆时调用的方法,将密码输入框的参数传过来,返回证书的主从账号信息,并会在Keychain中存储session,附应用可以通过调用相应的方法找到Keychain中存储的session直接登录成功
    */
    - (Account *)ssoLogin:(NSString*) password
    {
        int ssoLocalListenPort = [[L4Proxy sharedInstance] startLocalListen:ssoDesStr];
        if (ssoLocalListenPort > 0) {
            NSString *ssoHost = [NSString stringWithFormat:@"https://%@:%d",LOCAL_HOST, ssoLocalListenPort];
            NSString *retJson = [[SsoAuth sharedInstance] ssoAuthByCert:password withAppID:appId withServerAddress:ssoHost];
            NSLog(@"retJson = %@", retJson);
            NSError *error = nil;
            NSDictionary* result = [NSJSONSerialization JSONObjectWithData:[retJson dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:&error];
            NSLog(@"%@",result);
            if (error == nil && [@"success" isEqualToString:[result objectForKey:@"status"]]) {
                if(_account == nil) {
                    _account = [[Account alloc] init];
                }
                _account.name = [result objectForKey:@"masterAccout"];
                _account.token = [result objectForKey:@"token"];
                return _account;
            } else {
                NSString *message = [result objectForKey:@"message"];
                if(message == nil)
                {
                    message = @"请检查网络";
                }
                UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:@"提示" message:message delegate:nil cancelButtonTitle:@"确认" otherButtonTitles:nil, nil];
                [alertView show];
                
                NSLog(@"单点登录JSON解析失败, error:%@", error);
                return nil;
            }
        } else {
            return nil;
        }
    }


    4、动态更改app的显示模式(文件夹目录或者默认报表)

          上步的第4步骤,通过VPN调用服务器接口,获取配置文件,就是为了获取XML文件,每次启动都重新获取XML文件,所以可以在后台对XML文件内容进行更改,下次启动的时候,就会显示新更改的模式。

    - (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        NSString *str = [NSString stringWithFormat:@"http://127.0.0.1:%d/MicroStrategy/findDocumentId?loginname=%@",constant.webPort,certName];
        NSString *urlString = [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        NSURL *url = [NSURL URLWithString:urlString];
        NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
        NSURLResponse *response = nil;
        NSError *error = nil;
        NSData *allStringdata = [NSURLConnection  sendSynchronousRequest:request returningResponse:&response error:&error];
        NSString *allString = [[NSString alloc] initWithData:allStringdata encoding:NSUTF8StringEncoding];
        //保存到沙盒目录下
        NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
        NSString *xmlPath1 = [path stringByAppendingString:@"/Preferences.xml"];
        [allString writeToFile:xmlPath1 atomically:YES encoding:NSUTF8StringEncoding error:nil];
        return YES;
    }
     


             XML文件的获取,用浏览器登录mstr的mobile server,在mobile配置的地方,进行主屏幕的配置。之后会在mstr服务器的安装路径下找到一个刚生成的XML文件,例如,D:\apache-tomcat-6.0.36\webapps\MicroStrategyMobile\WEB-INF\xml\mobile。

             注意:取出的XML文件需要把服务器地址改为本地,端口号改为本地监听端口,项目地址不改。

          5、服务器集群,负载均衡的使用。

             负载均衡的使用,不需要app作何更改。由于VPN的使用app中只有本地地址127.0.0.1和监听端口号的存在。同样配置文件XML文件,里面的项目地址也无须更改。
     

  • 相关阅读:
    仿网吧游戏菜单-超好用
    C++零基础教程(引用)
    一个被清华大学辞退的50岁副教授
    Google Earth Engine(GEE)——
    JS DataTable中导出PDF右侧列被截断的问题解决
    《最新出炉》系列入门篇-Python+Playwright自动化测试-52- 字符串操作 - 下篇
    ARM通用中断控制器GIC之中断控制
    【浅谈DBA 最重要的素质---读书笔记】
    搜索技术【广度优先搜索】 - 简介 & 分支限界法
    “Spark+Hive”在DPU环境下的性能测评 | OLAP数据库引擎选型白皮书(24版)DPU部分节选
  • 原文地址:https://blog.csdn.net/q2919761440/article/details/133469049