我们正在构建一个
Worker
服务,我们希望将其托管在 Docker 容器中。该容器与我们的本地 SharePoint 服务器的 REST API 进行交互。 SharePoint REST API 中的身份验证使用 Windows 身份验证。
当我从 Visual Studio Code 运行下面的代码(在我的 Windows 开发计算机上使用
dotnet run
)时,代码可以正常运行,不会引发异常。
var opts = new RestClientOptions("https://sharepoint.domain.local");
opts.Credentials = new NetworkCredential("username", "password", "domain.local");
var spclient = new RestClient(opts);
var req = new RestRequest("_api/lists/getbytitle('MY_LIST')/items", Method.Get);
var resp = spclient.Execute(req);
_logger.LogDebug("Status code {x} returned from API call {y}", resp.StatusCode, resp.ResponseUri);
_logger.LogTrace("Raw response from {url}. Content: {raw}", resp.ResponseUri, resp.Content);
if(!resp.IsSuccessful)
{
throw new Exception();
}
现在,当我在 Docker 容器中运行相同的代码时,API 调用失败,并且我从 SharePoint REST API 获取
Unauthorized
状态代码,并具有以下 JSON 响应:
{
"odata.error": {
"code": "-2147024891, System.UnauthorizedAccessException",
"message": {
"lang": "en-US",
"value": "Access denied. You do not have permission to perform this action or access this resource."
}
}
}
出于测试目的,我使用与在开发计算机上使用的相同的用户名/密码。我确定提供了用户名和密码并且不为空。
我还尝试使用以下代码指定
NTLM
。行为没有改变:
CredentialCache cc = new CredentialCache();
cc.Add("https://sharepoint.domain.local", "NTLM", "username", "password", "domain.local");
var opts = new RestClientOptions("https://sharepoint.domain.local");
opts.Credentials = cc;
var spclient = new RestClient(opts);
var req = new RestRequest("_api/lists/getbytitle('MY_LIST')/items", Method.Get);
var resp = spclient.Execute(req);
_logger.LogDebug("Status code {x} returned from API call {y}", resp.StatusCode, resp.ResponseUri);
_logger.LogTrace("Raw response from {url}. Content: {raw}", resp.ResponseUri, resp.Content);
if(!resp.IsSuccessful)
{
throw new Exception();
}
请问有什么想法可以让它发挥作用吗?
如果其他人遇到此问题,您需要将一些库添加到容器映像中才能正常工作。首先,从这段代码开始:
var opts = new RestClientOptions("https://sharepoint.domain.local");
opts.Credentials = new NetworkCredential("username", "password", "domain.local");
var spclient = new RestClient(opts);
var req = new RestRequest("_api/lists/getbytitle('MY_LIST')/items", Method.Get);
var resp = spclient.Execute(req);
_logger.LogDebug("Status code {x} returned from API call {y}", resp.StatusCode, resp.ResponseUri);
_logger.LogTrace("Raw response from {url}. Content: {raw}", resp.ResponseUri, resp.Content);
if(!resp.IsSuccessful)
{
throw new Exception();
}
接下来,构建一个具有类似内容的
Dockerfile
:
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /source
# copy csproj and restore as distinct layers
COPY ./src .
RUN dotnet restore
# publish app and libraries
RUN dotnet publish -c release -o /app
# final stage
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
# Install necessary packages for NTLM/Kerberos
RUN apt-get update && apt-get install -y libkrb5-3 libgssapi-krb5-2 gss-ntlmssp && rm -rf /var/lib/apt/lists/*
# Create the ./logs directory
RUN mkdir -p ./logs
COPY --from=build /app .
ENTRYPOINT [ "dotnet", "my.application.dll" ]