在一线员工下班时限制对Microsoft Teams 的访问

概述

工作时间是一项功能,允许管理员限制 Android 和 iOS 移动设备上轮班员工对 Microsoft Teams 的访问。 这些控件专为自带设备 (BYOD) 或公司拥有的一线员工专用设备方案而设计。 详细了解一线设备方案

使用此功能,可以在下班的一线员工打开 Teams 时阻止对 Teams 的访问或显示警告消息。 在以下的情况下,请考虑为一线员工启用工作时间:

  • 你担心一线员工如果访问工作应用,他们会在工作时间外要求工资。
  • 当地法律和法规要求在员工下班时限制对工作应用的访问。

运作方式

当一线员工打卡到轮班并打开 Teams 时,应用会检查该工作人员是开班还是下班。

  • 如果工作人员在轮班,他们可以访问 Teams。
  • 如果工作人员在 Teams 打开时下班,则辅助角色将看到阻止或警告屏幕。
    • 如果配置了块屏幕,则辅助角色在轮班之前无法访问 Teams。
    • 如果配置了警告屏幕,辅助角色可以将其关闭,并自行决定是否使用 Teams。
  • 如果工作人员在打卡时使用 Teams,则工作人员在打卡后会看到应用的阻止或警告屏幕。

阻止访问屏幕和警告屏幕的屏幕截图。

除了工作时间,我们建议你还设置静默时间,以在工作人员下班时自动将 Teams 通知静音。

设置工作时间

按照以下步骤为一线启用工作时间。

为 Android 和 iOS 配置应用保护策略

使用Microsoft Intune应用保护策略来配置工作时间,以阻止或警告对 Android 和 iOS 设备上的 Teams 的访问。 有关策略设置的详细信息,请参阅:

将劳动力管理系统 (WFM) 连接到 workingTimeSchedule API

创建应用程序

  1. 在 Microsoft Entra 中为 workingTimeSchedule 图形 API创建应用程序。

    注册应用程序时,请确保选择 “此组织目录中的帐户仅 (单个租户) ”选项,以便只有租户中的用户可以使用该应用程序。 若要了解详细信息,请参阅使用 Microsoft 标识平台注册应用程序

  2. 使用所需的范围 Schedule-WorkingTime.ReadWrite.All添加用于调用图形 API的隐藏应用程序权限。

    1. 在 Azure 门户中登录到应用程序。

    2. 转到“ 清单 ”选项卡。你将看到一个 JSON,其中包含应用程序的完整定义。

    3. 在清单末尾,添加 requiredResourceAccess 属性。

      此属性指定应用程序需要访问的权限集。 换句话说,它包含应用程序可以调用的所有 API。 如果此属性已存在于清单中,则 API 已向其授予一些权限。

    4. 在数组中 requiredResourceAccess ,添加 ID 为 的对象 00000003-0000-0000-0000-c000-0000000000000000 ,以指定 Graph 应用程序的权限。

      如果数组中 requiredResourceAccess 已有一个具有相同 ID 的对象,则只需在 resourceAccess 数组中添加以下内容:

      • 具有新隐藏权限 0b21c159-dbf4-4dbb-a6f6-490e412c716e的 ID 的对象。
      • 权限的类型。 在本例中为 Role

      下面是清单末尾可能如下所示的示例:

      {
        ...
        "preAuthorizedApplications": [],
        "publisherDomain": "microsoft.onmicrosoft.com",
        "replyUrlsWithType": [
          {
            "url": "https://localhost:44321/signin-oidc",
            "type": "Web"
          },
          {
            "url": "https://localhost:44321/",
            "type": "Web"
          }
        ],
        "requiredResourceAccess": [
          {
            "resourceAppId": "00000003-0000-0000-c000-000000000000",
            "resourceAccess": [
              {
                "id": "0b21c159-dbf4-4dbb-a6f6-490e412c716e",
                "type": "Role"
              }
            ]
          }
        ],
        "samlMetadataUrl": null,
        "signInUrl": null,
        "signInAudience": "AzureADMyOrg",
        "tags": [],
        "tokenEncryptionKeyId": null
      }
      
    5. 保存更改。

必须是租户管理员才能执行此步骤。

  1. 在浏览器中,转到 https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id={ClientAppId}&response_type=code&scope=https://graph.microsoft.com/.default
  2. 在 URL 中,将 替换为 ClientAppId 应用 ID。
  3. 在同意对话框中,选择“ 接受” ,向租户范围的管理员授予对应用程序的新隐藏权限的同意。

从应用程序调用 Graph

下面介绍如何使用 C# 中的示例代码从应用程序调用 Graph 终结点。

  1. 使用 .NET 6 或 .NET 7 SDK 创建新的控制台项目。

  2. Microsoft.Identity.Client安装 NuGet 包。

  3. 打开 program.cs 文件,将以下示例代码复制并粘贴到该文件中:

        using System.Text;
      using Microsoft.Identity.Client;
      var userId = "928bf23a-81e8-47c9-ad54-2c0206248afe";
      var path = Path.Combine(Path.GetTempPath(),
      "workingTimeTokenGenerator.txt");
    
      string? accessToken;
      if (!File.Exists(path) || (DateTime.UtcNow - new
      FileInfo(path).LastWriteTimeUtc).TotalMinutes > 59)
      {
        var clientId = "00001111-aaaa-2222-bbbb-3333cccc4444";
        var clientSecret = "Aa1Bb~2Cc3.-Dd4Ee5Ff6Gg7Hh8Ii9_Jj0Kk1Ll2";
        var tenantId = "cad3e174-69d3-4707-abd2-f527f45c367a";
        var scopes = new string[] { "00000003-0000-0000-c000-000000000000/.default" };
    
        var app = ConfidentialClientApplicationBuilder.Create(clientId)
          .WithClientSecret(clientSecret)
          .Build();
    
        var result = await app.AcquireTokenForClient(scopes)
          .WithAuthority(AzureCloudInstance.AzurePublic, tenantId)
          .ExecuteAsync();
    
        accessToken = result.AccessToken;
        File.WriteAllText(path, accessToken);
      }
      else
      {
        accessToken = File.ReadAllText(path);
      }
    
      int number;
    
      while (true)
      {
        Console.WriteLine("Press 1 for startWorkingTime, 2 for endWorkingTime.");
        var choice = Console.ReadLine();
        if (!Int32.TryParse(choice, out number) || !new[] { 1, 2}.Contains(number))
        {
          Console.WriteLine("Out-of-range election.");
          continue;
        }
    
        break;
      }
    
      Console.WriteLine("Performing request...");
      var httpClient = new HttpClient();
      var message = new HttpRequestMessage
      {
        Method = HttpMethod.Post,
        RequestUri = new
      Uri($"https://graph.microsoft.com/beta/users/{userId}/solutions/schedule/{(number == 1 ? "startWorkingTime" : "endWorkingTime")}")
      };
      message.Headers.Add("Authorization", $"Bearer {accessToken}");
      message.Content = new StringContent("", Encoding.UTF8,
      "application/json");
      var response = await httpClient.SendAsync(message);
      if (!response.IsSuccessStatusCode)
      {
        string? content = null;
        try
        {
          content = await response.Content?.ReadAsStringAsync();
        }
        catch
        {
        }
    
        Console.WriteLine($"Graph returned a non success status code: 
      {response.StatusCode}. Reason phrase: {response.ReasonPhrase}." +
          (content is null ? "Unable to get the response body." :
      $"Content: {content}"));
      }
      else
      {
        Console.WriteLine($"Graph returned a success status code: 
      {response.StatusCode}.");
      }
    
      Console.WriteLine("Press any key to exit.");
      _ = Console.ReadKey();
    
  4. 在代码中,更改以下内容:

    • tenantId:将 替换为租户 ID。
    • clientId:将 替换为应用程序的 ID。
    • clientSecret:必须在应用程序的 身份验证 部分中添加客户端密码。 还可以选择使用安全证书并相应地更改代码。
    • userId:将 替换为要向其应用 inWorkingTime 或 outOfWorkingTime 策略的用户。

设置静默时间

此步骤是可选的,但建议这样做。

在 Intune 中配置静默时间策略,以便在非工作时间自动将一线员工的 Teams 通知静音。 详细了解如何 创建静默时间策略

常见问题解答

是否需要在 Teams 中使用排班应用才能利用此功能?

否,此功能依赖于来自WFM的时钟输入/输出信号。

如果没有时钟输入/输出系统,是否可以使用工作时间?

否,需要使用时钟输入/输出信号才能使用此功能。