Drupal 10内容分类标记接口请求遭遇403认证错误求助
问题描述
在Drupal 10中通过Blazor发送POST请求上传文件到文件端点可成功执行,但调用内容端点创建自定义「Sharepoint Resources」类型节点时,返回403禁止错误,提示「This authentication type is not allowed」。需要实现将上传的文件关联到该自定义内容类型,并添加标签。
错误原因分析
- Drupal REST认证配置限制:Drupal默认可能未允许Basic认证用于节点创建的REST请求,或者对应角色缺少创建「Sharepoint Resources」内容的权限。
- 请求数据不完整:现有代码未将上传得到的文件ID关联到节点的文件字段,也未使用选中的标签值。
- REST格式/权限配置缺失:未确保「Sharepoint Resources」内容类型的REST端点启用了JSON格式,且对应用户角色有操作权限。
修复步骤
1. 配置Drupal后台权限与REST设置
- 启用RESTful Web Services和Serialization模块。
- 进入
/admin/config/services/rest,找到Node的REST配置,确保:- 允许
POST方法。 - 勾选
Basic authentication作为认证方式。 - 勾选
json作为请求/响应格式。
- 允许
- 进入
/admin/people/permissions,给当前认证用户(如admin)授予:Create sharepoint_resources content权限。Access POST on Node resource权限。Create file权限(已存在,否则文件上传不会成功)。
2. 修正Blazor代码中的请求逻辑
需要完成以下修改:
- 将上传得到的文件ID关联到自定义内容类型的文件字段(假设字段名为
field_shared_file)。 - 将选中的标签值添加到节点的标签字段(假设字段名为
field_tags,且为分类术语引用字段)。 - 确保请求头正确,避免重复设置导致的问题。
完整修正代码
@page "/upload" @rendermode InteractiveServer @using Microsoft.AspNetCore.Components.Forms @using System.Net.Http @using System.Net.Http.Headers @using System.IO @using Newtonsoft.Json.Linq @using System.Text @using System.Net @using Newtonsoft.Json <PageTitle>Upload</PageTitle> <h3>Upload File</h3> <label for="fileInput">Select a file to upload:</label> <InputFile id="fileInput" OnChange="HandleFileChange" /> <label for="tag">Choose a tag:</label> <select @bind="tag" name="tag" id="tag"> <option value="hr">HR</option> <option value="connectcare">ConnectCare</option> </select> <button @onclick="UploadFile">Upload File</button> <p>@uploadResult</p> @code { private string uploadResult; private IBrowserFile selectedFile; private string tag; private List<UploadedFile> uploadedFiles = new List<UploadedFile>(); // 自定义类用于存储上传文件信息 public class UploadedFile { public string FileName { get; set; } public string FileId { get; set; } } private async Task HandleFileChange(InputFileChangeEventArgs e) { selectedFile = e.File; } private async Task<byte[]> ReadFileAsync(IBrowserFile file) { using (var memoryStream = new MemoryStream()) { await file.OpenReadStream().CopyToAsync(memoryStream); return memoryStream.ToArray(); } } private async Task UploadFile() { if (selectedFile == null || string.IsNullOrEmpty(tag)) { uploadResult = "请选择文件和标签"; return; } var handler = new HttpClientHandler() { CookieContainer = new CookieContainer(), UseCookies = true, UseDefaultCredentials = false }; using (var httpClient = new HttpClient(handler)) { httpClient.BaseAddress = new Uri("http://localhost/drupal10/web/"); // 设置Basic认证头 var authValue = Convert.ToBase64String(Encoding.UTF8.GetBytes("admin:Testingdrupal")); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authValue); // 提前设置Accept头,避免重复添加 httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); // 1. 上传文件到Drupal对应内容类型的文件字段端点 var fileBytes = await ReadFileAsync(selectedFile); var fileContent = new ByteArrayContent(fileBytes); fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = $"\"{selectedFile.Name}\"" }; var fileUploadResponse = await httpClient.PostAsync("file/upload/node/sharepoint_resources/field_shared_file", fileContent); if (!fileUploadResponse.IsSuccessStatusCode) { uploadResult = $"文件上传失败: {await fileUploadResponse.Content.ReadAsStringAsync()}"; return; } var fileUploadResponseContent = await fileUploadResponse.Content.ReadAsStringAsync(); var fileJsonResponse = JObject.Parse(fileUploadResponseContent); var fileId = fileJsonResponse["fid"][0]["value"].ToString(); // 2. 创建Sharepoint Resources节点,关联文件和标签 var nodeData = new { type = new { target_id = "sharepoint_resources" }, title = new { value = selectedFile.Name }, // 使用文件名作为标题更合理 field_shared_file = new[] { new { target_id = fileId } }, field_tags = new[] { new { target_id = tag } // 若标签是术语ID,替换为对应数值 } }; var nodeContent = new StringContent(JsonConvert.SerializeObject(nodeData), Encoding.UTF8, "application/json"); var response = await httpClient.PostAsync("node?_format=json", nodeContent); if (response.IsSuccessStatusCode) { uploadResult = $"内容创建成功,文件ID: {fileId},标签: {tag}"; uploadedFiles.Add(new UploadedFile { FileName = selectedFile.Name, FileId = fileId }); } else { uploadResult = $"创建内容失败: {response.StatusCode},响应内容: {await response.Content.ReadAsStringAsync()}"; } } } }
关键说明
- 文件上传端点路径修改为
file/upload/node/sharepoint_resources/field_shared_file,确保对应自定义内容类型的文件字段,而非默认的article类型字段。 - 节点数据中添加了
field_shared_file字段关联上传的文件ID,field_shared_file字段关联选中的标签值(需根据实际字段名调整)。 - 增加了输入校验,确保文件和标签都已选择。
- 统一设置Accept头,避免重复添加导致的潜在问题。
内容的提问来源于stack exchange,提问作者er280652
相关产品推荐
相关产品推荐

