ソースを参照

feat: IM token 改为后端返回

陈文艺 3 ヶ月 前
コミット
98bb2ff22c

+ 1 - 1
Lanu.xcodeproj/project.pbxproj

@@ -106,9 +106,9 @@
 				Manager/IM/Emoji/LNEmojiData.swift,
 				Manager/IM/Emoji/LNIMEmojiManager.swift,
 				"Manager/IM/Emoji/String+TUIEmoji.swift",
-				Manager/IM/GenerateTestUserSig.m,
 				Manager/IM/LNIMManager.swift,
 				Manager/IM/LNIMMessageData.swift,
+				"Manager/IM/Network/LNHttpManager+IM.swift",
 				"Manager/IM/TUIUtils/String+TUILocalized.swift",
 				"Manager/IM/TUIUtils/V2TIMConversation+Extension.swift",
 				"Manager/IM/TUIUtils/V2TIMMessage+Extension.swift",

+ 0 - 2
Lanu/Lanu-Bridging-Header.h

@@ -8,5 +8,3 @@
 #import <SDWebImage/SDWebImage.h>
 
 @import ImSDK_Plus;
-
-#import "GenerateTestUserSig.h"

+ 0 - 89
Lanu/Manager/IM/GenerateTestUserSig.h

@@ -1,89 +0,0 @@
-
-/*
- * Module:   GenerateTestUserSig
- *
- * Function:  Used to generate UserSig for testing. UserSig is a security signature designed by Tencent Cloud for its cloud services.
- *           It is calculated based on SDKAppID, UserID, and EXPIRETIME using the HMAC-SHA256 encryption algorithm.
- *
- * Attention: Do not use the code below in your commercial application. This is because:
- *
- *            The code may be able to calculate UserSig correctly, but it is only for quick testing of the SDK’s basic features, not for commercial applications.
- *            SECRETKEY in client code can be easily decompiled and reversed, especially on web.
- *            Once your key is disclosed, attackers will be able to steal your Tencent Cloud traffic.
- *
- *            The correct method is to deploy the UserSig calculation code and encryption key on your project server so that your application can request from your server a UserSig that is calculated whenever one is needed.
- *            Given that it is more difficult to hack a server than a client application, server-end calculation can better protect your key.
- *
- * Reference:https://intl.cloud.tencent.com/document/product/1047/34385
- */
-
-#import <Foundation/Foundation.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-#define SDKAPPID [GenerateTestUserSig currentSDKAppid]
-#define SECRETKEY [GenerateTestUserSig currentSecretkey]
-
-
-/**
- * Tencent Cloud SDKAppID. Set it to the SDKAppID of your account.
- *
- * You can view your SDKAppID after creating an application in the [Tencent Cloud IM console](https://console.intl.cloud.tencent.com/im).
- * SDKAppID uniquely identifies a Tencent Cloud account.
- */
-
-static const int public_SDKAPPID = 20030346;
-
-
-/**
- *  Signature validity period, which should not be set too short
- *
- *  Time unit: second
- *  Default value: 604800 (7 days)
- */
-static const int EXPIRETIME = 604800;
-
-
-/**
- * Follow the steps below to obtain the key required for UserSig calculation.
- *
- * Step 1. Log in to the [Tencent Cloud IM console](https://console.intl.cloud.tencent.com/im), and create an application if you don’t have one.
- * Step 2. Click Application Configuration to go to the basic configuration page and locate Account System Integration.
- * Step 3. Click View Key to view the encrypted key used for UserSig calculation. Then copy and paste the key to the variable below.
- *
- * Note: this method is for testing only. Before commercial launch, please migrate the UserSig calculation code and key to your backend server to prevent key disclosure and traffic stealing.
- * Reference:https://intl.cloud.tencent.com/document/product/1047/34385
- */
-static NSString * const public_SECRETKEY = @"a063a1a88b743dacba7f969b70e0b3aec161be06f1326a3913032c5632ed28f9";
-
-
-@interface GenerateTestUserSig : NSObject
-
-
-// Get the current SDKAppID and SecretKey
-
-+ (unsigned int)currentSDKAppid;
-
-+ (NSString *)currentSecretkey;
-
-/**
- * Calculate UserSig
- *
- * The asymmetric encryption algorithm HMAC-SHA256 is used in the function to calculate UserSig based on SDKAppID, UserID, and EXPIRETIME.
- *
- * Attention: Do not use the code below in your commercial application. This is because:
- *
- * The code may be able to calculate UserSig correctly, but it is only for quick testing of the SDK’s basic features, not for commercial applications.
- * SECRETKEY in client code can be easily decompiled and reversed, especially on web.
- * Once your key is disclosed, attackers will be able to steal your Tencent Cloud traffic.
- *
- * The correct method is to deploy the UserSig calculation code and encryption key on your project server so that your application can request from your server a UserSig that is calculated whenever one is needed.
- * Given that it is more difficult to hack a server than a client application, server-end calculation can better protect your key.
- *
- * Reference:https://intl.cloud.tencent.com/document/product/1047/34385
- */
-
-+ (NSString *)genTestUserSig:(NSString *)identifier;
-@end
-
-NS_ASSUME_NONNULL_END

+ 0 - 99
Lanu/Manager/IM/GenerateTestUserSig.m

@@ -1,99 +0,0 @@
-#import "GenerateTestUserSig.h"
-#import <CommonCrypto/CommonCrypto.h>
-#import <zlib.h>
-
-@implementation GenerateTestUserSig
-
-+ (unsigned int)currentSDKAppid {
-    return public_SDKAPPID;
-}
-
-+ (NSString *)currentSecretkey {
-    return public_SECRETKEY;
-}
-
-
-+ (NSString *)genTestUserSig:(NSString *)identifier
-{
-    CFTimeInterval current = CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970;
-    long TLSTime = floor(current);
-    NSMutableDictionary *obj = [@{@"TLS.ver": @"2.0",
-                                  @"TLS.identifier": identifier,
-                                  @"TLS.sdkappid": @(SDKAPPID),
-                                  @"TLS.expire": @(EXPIRETIME),
-                                  @"TLS.time": @(TLSTime)} mutableCopy];
-    NSMutableString *stringToSign = [[NSMutableString alloc] init];
-    NSArray *keyOrder = @[@"TLS.identifier",
-                          @"TLS.sdkappid",
-                          @"TLS.time",
-                          @"TLS.expire"];
-    for (NSString *key in keyOrder) {
-        [stringToSign appendFormat:@"%@:%@\n", key, obj[key]];
-    }
-    NSLog(@"%@", stringToSign);
-    //NSString *sig = [self sigString:stringToSign];
-    NSString *sig = [self hmac:stringToSign];
-
-    obj[@"TLS.sig"] = sig;
-    NSLog(@"sig: %@", sig);
-    NSError *error = nil;
-    NSData *jsonToZipData = [NSJSONSerialization dataWithJSONObject:obj options:0 error:&error];
-    if (error) {
-        NSLog(@"[Error] json serialization failed: %@", error);
-        return @"";
-    }
-
-    const Bytef* zipsrc = (const Bytef*)[jsonToZipData bytes];
-    uLongf srcLen = jsonToZipData.length;
-    uLong upperBound = compressBound(srcLen);
-    Bytef *dest = (Bytef*)malloc(upperBound);
-    uLongf destLen = upperBound;
-    int ret = compress2(dest, &destLen, (const Bytef*)zipsrc, srcLen, Z_BEST_SPEED);
-    if (ret != Z_OK) {
-        NSLog(@"[Error] Compress Error %d, upper bound: %lu", ret, upperBound);
-        free(dest);
-        return @"";
-    }
-    NSString *result = [self base64URL: [NSData dataWithBytesNoCopy:dest length:destLen]];
-    return result;
-}
-
-+ (NSString *)hmac:(NSString *)plainText
-{
-    const char *cKey  = [SECRETKEY cStringUsingEncoding:NSASCIIStringEncoding];
-    const char *cData = [plainText cStringUsingEncoding:NSASCIIStringEncoding];
-
-    unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
-
-    CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
-
-    NSData *HMACData = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
-    return [HMACData base64EncodedStringWithOptions:0];
-}
-
-+ (NSString *)base64URL:(NSData *)data
-{
-    NSString *result = [data base64EncodedStringWithOptions:0];
-    NSMutableString *final = [[NSMutableString alloc] init];
-    const char *cString = [result cStringUsingEncoding:NSUTF8StringEncoding];
-    for (int i = 0; i < result.length; ++ i) {
-        char x = cString[i];
-        switch(x){
-            case '+':
-                [final appendString:@"*"];
-                break;
-            case '/':
-                [final appendString:@"-"];
-                break;
-            case '=':
-                [final appendString:@"_"];
-                break;
-            default:
-                [final appendFormat:@"%c", x];
-                break;
-        }
-    }
-    return final;
-}
-
-@end

+ 13 - 3
Lanu/Manager/IM/LNIMManager.swift

@@ -27,7 +27,6 @@ extension String {
 
 class LNIMManager: NSObject {
     private static let appId: Int32 = 20030346
-    private static let secretKey = "a063a1a88b743dacba7f969b70e0b3aec161be06f1326a3913032c5632ed28f9"
     
     static var shared = LNIMManager()
     static let officialId = "10000"
@@ -137,7 +136,6 @@ extension LNIMManager: LNAccountManagerNotify {
         }
         
         // 登录
-        let userSig = GenerateTestUserSig.genTestUserSig(myUid)
         let loginSuccessBlock = { [weak self] in
             guard let self else { return }
             reloadConversationList()
@@ -147,7 +145,11 @@ extension LNIMManager: LNAccountManagerNotify {
             return
         }
         
-        V2TIMManager.sharedInstance().login(userID: myUid, userSig: userSig, succ: loginSuccessBlock)
+        getIMSignToken { [weak self] token in
+            guard let self else { return }
+            guard let token else { return }
+            V2TIMManager.sharedInstance().login(userID: myUid, userSig: token, succ: loginSuccessBlock)
+        }
     }
     
     func onUserLogout() {
@@ -158,6 +160,14 @@ extension LNIMManager: LNAccountManagerNotify {
     }
 }
 
+extension LNIMManager {
+    private func getIMSignToken(handler: @escaping (String?) -> Void) {
+        LNHttpManager.shared.getIMSign { token, err in
+            handler(token)
+        }
+    }
+}
+
 extension LNIMManager {
     private func notifyConversationListChanged() {
         LNEventDeliver.notifyEvent {

+ 18 - 0
Lanu/Manager/IM/Network/LNHttpManager+IM.swift

@@ -0,0 +1,18 @@
+//
+//  LNHttpManager+IM.swift
+//  Lanu
+//
+//  Created by OneeChan on 2025/12/26.
+//
+
+import Foundation
+
+
+private let kNetPath_IM_Sign = "/im/userSign"
+
+
+extension LNHttpManager {
+    func getIMSign(completion: @escaping (String?, LNHttpError?) -> Void) {
+        post(path: kNetPath_IM_Sign, completion: completion)
+    }
+}

+ 10 - 2
Lanu/Views/Web/LNWebViewController.swift

@@ -14,10 +14,11 @@ import Combine
 
 class LNJumpWebViewConfig {
     let url: String
-    var customTitle: String = ""
+    let customTitle: String
     
-    init(url: String) {
+    init(url: String, title: String = "") {
         self.url = url
+        customTitle = title
     }
 }
 
@@ -80,6 +81,13 @@ extension LNWebViewController {
     private func buildWebView() -> UIView {
         let webConfig = WKWebViewConfiguration()
         
+        let tokenScript = WKUserScript(source: "window.localStorage.setItem('GAMI-web_auth_token', '\(LNAccountManager.shared.token)')",
+                                       injectionTime: .atDocumentStart, forMainFrameOnly: true)
+        webConfig.userContentController.addUserScript(tokenScript)
+        
+        let languageScript = WKUserScript(source: "window.localStorage.setItem('GAMI-web_app_locale', '\(LNAppConfig.shared.curLang.bundleName)')",
+                                          injectionTime: .atDocumentStart, forMainFrameOnly: true)
+        
         let webView = WKWebView(frame: .zero, configuration: webConfig)
         webView.navigationDelegate = self