在 Microsoft Graph 中生成用户时出现编码问题

问题描述 投票:0回答:1

发送到 /v1.0/users 的 POST 正文应该采用什么字符编码?

我在使用 Microsoft Graph 生成名称中带有重音字符的用户时遇到问题。

我使用以下身体:

{
    "accountEnabled":false,
    "displayName":"ADM Joost Müller",
    "userprincipalname":"[email protected]",
    "mailNickname":"admjmuller",
    "passwordProfile":{      
        "forceChangePasswordNextSignIn":true,
        "forceChangePasswordNextSignInWithMfa":true,
        "password":"Randompasswordgenerated"
    }
}

当在正文中使用上述 JSON 调用 POST 到 /v1.0/users 时,我得到以下对象:

@odata.context    : https://graph.microsoft.com/v1.0/$metadata#users/$entity
id                : xxxxxxxx-xxxx-xxxx-xxxx-a72a188e6d9a
businessPhones    : {}
displayName       : ADM Joost M�ller
givenName         : 
jobTitle          : 
mail              : 
mobilePhone       : 
officeLocation    : 
preferredLanguage : 
surname           : 
userPrincipalName : [email protected]

注意显示名称中的“�”。这不是 Powershell 中的显示问题,Azure 门户中的 Entra ID 边栏选项卡也显示此字符。 我已经尝试过将 JSON 强制转换为 UTF-8:

$enc = [System.Text.Encoding]::UTF8
$jsonutf8 = $enc.getstring($enc.getbytes($json))

但这并没有解决问题。

我尝试了各种搜索词,但找不到任何指向解决方案的内容。这可能是一件微不足道的事情,但如果是的话,我使用了错误的搜索词......

实际代码:

function Encode {
  Param(
    [string]$text
  )
  $enc = [System.Text.Encoding]::Utf8
  return $enc.getstring($enc.getbytes($text))
}

function Invoke-GraphPost {
  [cmdletbinding()]
  Param(
    [parameter(Mandatory = $true)][string]$API,
    [parameter(Mandatory = $true)][string]$AccessToken,
    [parameter(Mandatory = $true)]$body,
    [parameter(Mandatory = $false)][string]$Apiversion = "v1.0"
  )
  $header = @{
    Authorization  = ("Bearer {0}" -f $AccessToken)
    'Content-Type' = 'application/json; charset=utf-8'
  }
  $bodyjson = Encode(ConvertTo-Json -InputObject $body -Compress)
  $URI = Encode(("https://graph.microsoft.com/{0}/{1}" -f $Apiversion, $API))
  try {
    $result = Invoke-RestMethod -Uri $URI -Method Post -Body $bodyjson -Headers $header
  }
  catch {
    $FailMessage = ("Unable to create graph POST request {0} with body {1}" -f $URI, $bodyjson)
    $module.failjson($FailMessage)
  }
  return $result
}

      $password = [System.Web.Security.Membership]::GeneratePassword(12, 4)
      $upnbase = New-EntraUserName -NameFormat "$adminprefix$format" -Voornaam $User.Roepnaam -Infix $User.Voorv_gebnaam -Achternaam $User.Geboortenaam -Domainname $admindomain
      $body = @{
        accountEnabled    = $false
        displayName       = ("ADM {0} {1}" -f $User.Roepnaam.Trim(), $User.Volledige_achternaam.Trim())
        mailNickname      = $upnbase
        userprincipalname = ("{0}@{1}" -f $upnbase, $admindomain)
        passwordProfile   = @{
          forceChangePasswordNextSignIn        = $true
          forceChangePasswordNextSignInWithMfa = $true
          password                             = $password
        }
      }
$newuser = Invoke-GraphPost -API users -AccessToken $token.access_token -body $body

其中

New-EntraUserName
根据名字、中缀和姓氏生成唯一的用户名(确切的代码与问题无关,对于 Joost Müller,生成的用户名是 admjmuller,因此没有重音)。

乔斯特

powershell character-encoding microsoft-graph-api invoke-restmethod
1个回答
1
投票

您的 请求正文以预期的 UTF-8 字符编码提交,原因如下:

  • 您的

    Encode
    函数是一个 no-op:它将字符串转换为 并从 UTF-8 字节表示形式返回,这样您最终会得到相同的 .NET 字符串(类型为
    [string]
    ,内部由UTF-16 Unicode代码单元组成)。

  • 因此,您将常规

    [string]
    实例传递给
    -Body
    参数,因此将使用哪种字符编码的决定委托给
    Invoke-RestMethod
    (以下内容也类似地适用于
    Invoke-WebRequest
    ):

    • 当您尝试通过 header 字段指示所需的编码时, - 您传递给

      'Content-Type' = 'application/json; charset=utf-8'
      的哈希表中的
      -Header
      条目 - PowerShell 7.3-,包括 Windows PowerShell ,不幸的是,遵守这一点,并且默认为ISO-8559-1编码

      • 但是,
        charset
        属性作为单独的
        -ContentType
        参数
      • 的一部分是受尊重的(见下文)。
    • PowerShell(核心) 7.4+ 现在也支持标头字段,并且在 charset

       属性的
      缺席中,现在默认为 UTF-8


解决方案

  • PowerShell 7.4+

    • 鉴于上述情况,您的代码应该按原样工作 - 除了您不需要多余的 
      Encode
    • 调用。
  • PowerShell 7.3-和 Windows PowerShell

    :
    • 选项 1:
      • 省略(毫无意义的)
        Encode
      • 调用。
      • 请勿将 
        Content-Type
         条目添加到 
        $header
      • 相反,为 -ContentType 'application/json; charset=utf-8' 调用添加
        Invoke-RestMethod
         参数。
    • 选项2:

      • 执行UTF-8编码自己字节数组传递给-Body

        参数:
        

        Invoke-RestMethod -Uri $URI -Method Post -Headers $header -Body ( [Text.UTF8Encoding]::new().GetBytes( (ConvertTo-Json -InputObject $body -Compress) ) )
        
        
© www.soinside.com 2019 - 2024. All rights reserved.