Áp dụng cho
SharePoint Foundation 2013 SP1 SharePoint Server 2016 SharePoint Server 2019 SharePoint Server Subscription Edition

Dấu hiệu

Sau khi bạn cài đặt các bản cập nhật bảo mật tháng 10 sau Microsoft SharePoint Server, một số kịch bản dòng công việc SharePoint 2010 Microsoft có thể bị chặn. Ngoài ra, thẻ sự kiện "6ksbk" được ghi nhật ký trong nhật ký Hệ thống Ghi nhật ký Hợp nhất SharePoint (ULS). 

Nguyên nhân

Để tăng cường tính bảo mật của dòng công việc SharePoint, SharePoint hiện chỉ hỗ trợ mã hóa ký tự UTF-8 cho các tệp dòng công việc .xoml. 

Lưu ý: Các công cụ dòng công việc SharePoint như SharePoint Designer, Microsoft Visual Studio và Nintex tạo các tệp dòng công việc .xoml bằng mã hóa ký tự UTF-8 theo mặc định. Khách hàng sẽ không bị ảnh hưởng bởi cải tiến bảo mật này trừ khi họ đã chỉnh sửa tệp .xoml dòng công việc của mình theo cách thủ công và chuyển đổi chúng thành mã hóa ký tự khác. Sự cố này được ghi lại trong bài viết KB này về khả năng cực kỳ hiếm gặp mà khách hàng có thể đã chọn thực hiện điều này.

Giải pháp

Nếu bạn đã sửa tệp .xoml dòng công việc theo cách thủ công và chuyển đổi nó thành một mã hóa ký tự khác UTF-8, bạn sẽ cần sửa lại tệp để chuyển đổi nó trở lại UTF-8. Hãy đảm bảo khai báo XML của tệp xác định mã hóa là UTF-8, lưu tệp theo định dạng mã hóa ký tự UTF-8 với trình soạn thảo văn bản của bạn, rồi nộp lại.

Tập lệnh PowerShell sau đây có thể được sử dụng trong SharePoint Management Shell để quét các tệp .xoml dòng công việc trong tuyển tập trang SharePoint để xác định xem chúng có bị ảnh hưởng bởi thay đổi này hay không. Đầu ra IsGoodWorkflow sẽ được áp True cho các tệp .xoml dòng công việc sử dụng mã hóa ký tự UTF-8 và tương thích với thay đổi này. Đầu ra IsGoodWorkflow sẽ được False cho các tệp .xoml dòng công việc không sử dụng mã hóa ký tự UTF-8 và cần được sửa đổi.

<#
.SYNOPSIS
    Script to check character encoding of workflow .xoml files found in a site collection.
.DESCRIPTION
    This script checks the character encoding of workflow .xoml files found in a site collection based
    on the security improvement documented here: https://support.microsoft.com/topic/sharepoint-2010-workflows-might-be-blocked-by-enhanced-security-policy-kb5020238-eb91e24d-eea4-4490-a281-86503adc8b27
    
    This could be altered to take an SPWebApplication object, iterate through all SPSite objects in the Sites SPSiteCollection,
    and then iterate through all SPWeb subsites in the AllWebs SPWebCollection.

.EXAMPLE
    Get-WorkflowStatusForSite -SiteCollectionUrl https://sharepoint

.EXAMPLE
    Get-WorkflowStatusForSite -SiteCollectionUrl https://sharepoint -IgnoreSubSites
.INPUTS
    None
.OUTPUTS
    PSCustomObject with Site, Web, WorkflowFileName and IsGoodWorkflow Result

    Site                         Web                            WorkflowFileName       IsGoodWorkflow
    ----                         ---                            ----------------       --------------
    SPSite Url=http://sharepoint http://sharepoint/WorkflowTest 2010 Log Workflow.xoml           True
    SPSite Url=http://sharepoint http://sharepoint/WorkflowTest Another Test Log.xoml            True
.NOTES
    Version .1
#>
param(
    [Parameter(Position=2,HelpMessage="The site collection URL to validate.")]
    [string]$SiteCollectionUrl, 
    [Parameter(Position=3,HelpMessage="Ignore subsites below the top-level site in the site collection.")]
    [switch]$IgnoreSubSites
)

function IsGoodWorkflow
{
    param
    (
        [Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
        [System.Xml.XmlReader]$xmlReader
    )

    try {
        $xDoc = [System.Xml.Linq.XDocument]::Load($xmlReader)

        if ($null -ne $xDoc -and $null -ne $xDoc.Declaration -and $null -ne $xDoc.Declaration.Encoding)
        {
            if ($xdoc.Declaration.Encoding.ToLower() -ne "utf-8")
            {
                return $false
            }
        }
    }
    catch
    {
        return $false
    }
        

    return $true
}

function CheckWorkflowFile
{
    param
    (
        [Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
        [Microsoft.SharePoint.SPFile]$SPFile
    )

    $xmlReader = [System.Xml.XmlReader]::Create($SPFile.OpenBinaryStream())

    if ($null -ne $xmlReader)
    {
        $isGood = $xmlReader | IsGoodWorkflow

        $xmlReader.Close()
        $xmlReader.Dispose()
        
        return [PSCustomObject]@{
            Site = $SPFile.Item.Web.Site
            Web = $SPFile.Item.Web.Url
            WorkflowFileName = $SPFile.Name
            IsGoodWorkflow = $isGood
            }
    }
}

function CheckWorkflowsForWeb
{
    param
    (
        [Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
        [Microsoft.SharePoint.SPWeb]$SPWeb
    )

    write-host "Checking $SPweb"
    $WorkflowsList = $SPWeb.Lists["Workflows"]

    $results = @()

    if ($WorkflowsList)
    {
        Write-Host "Found: " $WorkflowsList.Title

        foreach ($listItem in $WorkflowsList.Items)
        {
            if ($listItem.File -and $listItem.File.Name.ToLower().EndsWith(".xoml"))
            {
                Write-Host "Found Workflow: " $listItem.File.Name
                $results += (CheckWorkflowFile $listItem.File)
            }
        }
    }
    return $results
}

function CheckWorkflowsForSite
{
    param
    (
    [Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
    [Microsoft.SharePoint.SPSite]$SPSite,
    [switch]$IgnoreSubSites
    )
    
    $results = @()

    if ($IgnoreSubSites)
    {
        $SPWeb = $SPSite.RootWeb

        $results += CheckWorkflowsForWeb $SPWeb

        $SPWeb.Dispose()
    }
    else
    {
        foreach ($SPWeb in $SPSite.AllWebs)
        {
            $results += CheckWorkflowsForWeb $SPWeb
            $SPWeb.Dispose()
        }
    }
    
    return $results
}

if ([string]::IsNullOrEmpty($SiteCollectionUrl))
{
    $SiteCollectionUrl = Read-Host "Please provide a site collection URL (Default: http://sharepoint)"
    if ([String]::IsNullOrEmpty($SiteCollectionUrl))
    {
        $SiteCollectionUrl = "http://sharepoint"
    }
}

$SPSite = Get-SPSite $SiteCollectionUrl -ErrorAction SilentlyContinue

if ($null -eq $SPSite)
{
    Write-Host "Site collection $SiteCollectionUrl not found." -ForegroundColor Red
    return;
}

$results = CheckWorkflowsForSite $SPSite

# Dispose of the Site
$SPSite.Dispose()

# Results can be exported to a CSV or manipulated
$results

Lịch sử thay đổi

Bảng sau đây tóm tắt một số thay đổi quan trọng nhất đối với chủ đề này.

Ngày

Mô tả

Ngày 22 tháng 11 năm 2022

Đã thêm ghi chú vào mục "Nguyên nhân" và cập nhật phần "Giải pháp thay thế" bằng tập lệnh PowerShell để quét tệp .xoml dòng công việc.

Bạn cần thêm trợ giúp?

Bạn muốn xem các tùy chọn khác?

Khám phá các lợi ích của gói đăng ký, xem qua các khóa đào tạo, tìm hiểu cách bảo mật thiết bị của bạn và hơn thế nữa.