iOS/OS X 代码示例
重要
2020 年 3 月之前发布的 Microsoft Rights Management Service SDK 版本已弃用;使用早期版本的应用程序必须更新为使用 2020 年 3 月版本。 有关完整详细信息,请参阅 弃用通知。
Microsoft Rights Management Service SDK 没有进一步增强功能。 强烈建议采用用于分类、标记和保护服务的 Microsoft 信息保护 SDK。
本主题向你介绍 iOS/OS X 版 RMS SDK 的重要代码元素。
注意在下面的示例代码和说明中,我们使用术语 MSIPC (Microsoft 信息保护和控制) 来引用客户端进程。
使用 Microsoft Rights Management SDK 4.2 - 重要方案
以下是摘取自一个较大示例应用程序的 Objective C 代码示例,表示对你学习此 SDK 十分重要的开发方案。 这些示例演示 Microsoft 受保护的文件格式(称为受保护的文件)的使用、自定义受保护的文件格式的使用以及自定义 UI 控件的使用。
方案:使用受 RMS 保护的文件
步骤 1:创建 MSProtectedData 对象
说明:通过 create 方法实例化 MSProtectedData 对象,该方法使用 MSAuthenticationCallback 实现服务身份验证,以便通过将 MSAuthenticationCallback 的实例作为参数 authenticationCallback 传递给 MSIPC API 来获取令牌。 请参阅以下示例代码部分中对 MSProtectedData protectedDataWithProtectedFile 的调用。
+ (void)consumePtxtFile:(NSString *)path authenticationCallback:(id<MSAuthenticationCallback>)authenticationCallback { // userId can be provided as a hint for authentication [MSProtectedData protectedDataWithProtectedFile:path userId:nil authenticationCallback:authenticationCallback options:Default completionBlock:^(MSProtectedData *data, NSError *error) { //Read the content from the ProtectedData, this will decrypt the data NSData *content = [data retrieveData]; }]; }
步骤 2:使用 Active Directory 身份验证库 (ADAL) 设置身份验证。
说明:此步骤中会介绍用于通过示例身份验证参数来实现 MSAuthenticationCallback 的 ADAL。 若要深入了解如何使用 ADAL,请参阅 Azure AD 身份验证库 (ADAL)。
// AuthenticationCallback holds the necessary information to retrieve an access token. @interface MsipcAuthenticationCallback : NSObject<MSAuthenticationCallback> @end @implementation MsipcAuthenticationCallback - (void)accessTokenWithAuthenticationParameters: (MSAuthenticationParameters *)authenticationParameters completionBlock: (void(^)(NSString *accessToken, NSError *error))completionBlock { ADAuthenticationError *error; ADAuthenticationContext* context = [ ADAuthenticationContext authenticationContextWithAuthority:authenticationParameters.authority error:&error ]; NSString *appClientId = @"com.microsoft.sampleapp"; NSURL *redirectURI = [NSURL URLWithString:@"local://authorize"]; // Retrieve token using ADAL [context acquireTokenWithResource:authenticationParameters.resource clientId:appClientId redirectUri:redirectURI userId:authenticationParameters.userId completionBlock:^(ADAuthenticationResult *result) { if (result.status != AD_SUCCEEDED) { NSLog(@"Auth Failed"); completionBlock(nil, result.error); } else { completionBlock(result.accessToken, result.error); } }]; }
步骤 3:通过 MSUserPolicy 对象的 MSUserPolicy accessCheck 方法,检查此用户对于该内容是否具有 Edit 权限。
- (void)accessCheckWithProtectedData:(MSProtectedData *)protectedData { //check if user has edit rights and apply enforcements if (!protectedData.userPolicy.accessCheck(EditableDocumentRights.Edit)) { // enforce on the UI textEditor.focusableInTouchMode = NO; textEditor.focusable = NO; textEditor.enabled = NO; } }
方案:使用模板创建新的受保护文件
此方案首先获取模板列表 MSTemplateDescriptor,再选择第一个模板以创建策略,然后创建和写入新的受保护文件。
步骤 1:获取模板列表
+ (void)templateListUsageWithAuthenticationCallback:(id<MSAuthenticationCallback>)authenticationCallback { [MSTemplateDescriptor templateListWithUserId:@"user@domain.com" authenticationCallback:authenticationCallback completionBlock:^(NSArray/*MSTemplateDescriptor*/ *templates, NSError *error) { // use templates array of MSTemplateDescriptor (Note: will be nil on error) }]; }
步骤 2:使用列表中的第一个模板创建 MSUserPolicy。
+ (void)userPolicyCreationFromTemplateWithAuthenticationCallback:(id<MSAuthenticationCallback>)authenticationCallback { [MSUserPolicy userPolicyWithTemplateDescriptor:[templates objectAtIndex:0] userId:@"user@domain.com" signedAppData:nil authenticationCallback:authenticationCallback options:None completionBlock:^(MSUserPolicy *userPolicy, NSError *error) { // use userPolicy (Note: will be nil on error) }]; }
步骤 3:创建 MSMutableProtectedData 并向其中写入内容。
+ (void)createPtxtWithUserPolicy:(MSUserPolicy *)userPolicy contentToProtect:(NSData *)contentToProtect { // create an MSMutableProtectedData to write content [contentToProtect protectedDataInFile:filePath originalFileExtension:kDefaultTextFileExtension withUserPolicy:userPolicy completionBlock:^(MSMutableProtectedData *data, NSError *error) { // use data (Note: will be nil on error) }]; }
方案:打开自定义受保护的文件
步骤 1:通过 serializedContentPolicy 创建 MSUserPolicy。
+ (void)userPolicyWith:(NSData *)protectedData authenticationCallback:(id<MSAuthenticationCallback>)authenticationCallback { // Read header information from protectedData and extract the PL /*------------------------------------------- | PL length | PL | ContetSizeLength | -------------------------------------------*/ NSUInteger serializedPolicySize; NSMutableData *serializedPolicy; [protectedData getBytes:&serializedPolicySize length:sizeof(serializedPolicySize)]; [protectedData getBytes:[serializedPolicy mutableBytes] length:serializedPolicySize]; // Get the user policy , this is an async method as it hits the REST service // for content key and usage restrictions // userId provided as a hint for authentication [MSUserPolicy userPolicyWithSerializedPolicy:serializedPolicy userId:@"user@domain.com" authenticationCallback:authenticationCallback options:Default completionBlock:^(MSUserPolicy *userPolicy, NSError *error) { }]; }
步骤 2:使用步骤 1 中的 MSUserPolicy 创建 MSCustomProtectedData,并从中读取信息。
+ (void)customProtectedDataWith:(NSData *)protectedData { // Read header information from protectedData and extract the protectedContentSize /*------------------------------------------- | PL length | PL | ContetSizeLength | -------------------------------------------*/ NSUInteger protectedContentSize; [protectedData getBytes:&protectedContentSize length:sizeof(protectedContentSize)]; // Create the MSCustomProtector used for decrypting the content // The content start position is the header length [MSCustomProtectedData customProtectedDataWithPolicy:userPolicy protectedData:protectedData contentStartPosition:sizeof(NSUInteger) + serializedPolicySize contentSize:protectedContentSize completionBlock:^(MSCustomProtectedData *customProtector, NSError *error) { //Read the content from the custom protector, this will decrypt the data NSData *content = [customProtector retrieveData]; NSLog(@"%@", content); }]; }
方案:使用自定义(临时)策略创建自定义受保护的文件
步骤 1:在用户提供了电子邮件地址的情况下,创建策略描述符。
说明:实际上,会使用来自设备接口的用户输入创建以下对象;MSUserRights 和 MSPolicyDescriptor。
+ (void)policyDescriptor { MSUserRights *userRights = [[MSUserRights alloc] initWithUsers:[NSArray arrayWithObjects: @"user1@domain.com", @"user2@domain.com", nil] rights:[MSEmailRights all]]; MSPolicyDescriptor *policyDescriptor = [[MSPolicyDescriptor alloc] initWithUserRights:[NSArray arrayWithObjects:userRights, nil]]; policyDescriptor.contentValidUntil = [[NSDate alloc] initWithTimeIntervalSinceNow:NSTimeIntervalSince1970 + 3600.0]; policyDescriptor.offlineCacheLifetimeInDays = 10; }
步骤 2:通过策略描述符 selectedDescriptor 创建自定义 MSUserPolicy。
+ (void)userPolicyWithPolicyDescriptor:(MSPolicyDescriptor *)policyDescriptor { [MSUserPolicy userPolicyWithPolicyDescriptor:policyDescriptor userId:@"user@domain.com" authenticationCallback:authenticationCallback options:None completionBlock:^(MSUserPolicy *userPolicy, NSError *error) { // use userPolicy (Note: will be nil on error) }]; }
步骤 3:创建 MSMutableCustomProtectedData 并向其写入内容,然后关闭。
+ (void)mutableCustomProtectedData:(NSMutableData *)backingData policy:(MSUserPolicy *)policy contentToProtect:(NSString *)contentToProtect { //Get the serializedPolicy from a given policy NSData *serializedPolicy = [policy serializedPolicy]; // Write header information to backing data including the PL // ------------------------------------ // | PL length | PL | ContetSizeLength | // ------------------------------------- NSUInteger serializedPolicyLength = [serializedPolicy length]; [backingData appendData:[NSData dataWithBytes:&serializedPolicyLength length:sizeof(serializedPolicyLength)]]; [backingData appendData:serializedPolicy]; NSUInteger protectedContentLength = [MSCustomProtectedData getEncryptedContentLengthWithPolicy:policy contentLength:unprotectedData.length]; [backingData appendData:[NSData dataWithBytes:&protectedContentLength length:sizeof(protectedContentLength)]]; NSUInteger headerLength = sizeof(serializedPolicyLength) + serializedPolicyLength + sizeof(protectedContentLength); // Create the MSMutableCustomProtector used for encrypting content // The content start position is the current length of the backing data // The encryptedContentSize content size is 0 since there is no content yet [MSMutableCustomProtectedData customProtectorWithUserPolicy:policy backingData:backingData protectedContentOffset:headerLength completionBlock:^(MSMutableCustomProtectedData *customProtector, NSError *error) { //Append data to the custom protector, this will encrypt the data and write it to the backing data [customProtector appendData:[contentToProtect dataUsingEncoding:NSUTF8StringEncoding] error:&error]; //close the custom protector so it will flush and finalise encryption [customProtector close:&error]; }]; }