Доступ до спільних папок на інших серверах із програми ASP.NET Core (версія програми, підключеної до мережі)

Сторінка оновлюється :
Дата створення сторінки :

Середовище перевірки роботи

Візуальна студія
  • Visual Studio 2022
ASP.NET Ядро
  • 8 (Бритвені сторінки, MVC)
Windows Server
  • 2022 (ASP.NET основні системні вимоги)
  • 2019 (сервер розгортання спільних папок)
ІВС
  • 10.0

Робоче середовище

Ми тестували його не у всіх випадках, але загалом він має працювати за таких умов:

Візуальна студія
  • Все, що може розвинути проєкт ASP.NET Core
ASP.NET Ядро
  • Будь-яка версія (MVC, Razor Pages, API)
Windows Server
  • Windows Server 2008 або пізнішої версії
ІВС
  • 7.0 або новішої версії

Передумовою

  • ASP.NET Основні програми призначені для роботи на IIS.
  • Оскільки він використовує API Windows для автентифікації, він не працює в інших пристроях, відмінних від Windows.

середовище

Це перевіряється в наступному середовищі.

Мета використання ПК і серверів
Windows 11 (локальна) Середовище для розробки програм.
SV2022Тест Середовище, в якому працює IIS і ASP.NET Core. Доступ до спільної папки SV2019Test можна отримати звідси
SV2019Тест Сервери зі спільними папками

Крім того, різні налаштування такі.

Значення назви параметра
Ім'я користувача Access SharedUser
Ім'я спільної папки Спільна папка

Створення сервера спільних папок

Створення користувача

Створіть користувача для доступу до загальної папки. У цьому випадку ми створимо локальний обліковий запис, але якщо ви маєте справу з серверами та обліковими записами в такому домені, як Active Directory, ви також можете використовувати його.

Процес створення користувача виходить за рамки цих порад, тому ми не будемо вдаватися в подробиці.

SharedUser У цьому випадку ми створимо його з ім'ям . Оскільки цей користувач не керує екраном і не змінює налаштування, пароль змінити не можна.

Якщо ви залишите значення за замовчуванням, ви зможете увійти до системи за допомогою цього користувача за допомогою віддаленого робочого столу тощо, тому, будь ласка, видаліть його з групи Users .

Створення спільної папки

Не має значення, де ви його створюєте. Це пов'язано з тим, що інші сервери не дбають про розташування фізичної папки. У цьому випадку ми створимо папку з ім'ям безпосередньо під SharedFolder диском C і поділимося нею.

Відкрийте властивості та налаштуйте параметри спільного доступу.

Ім'я спільної папки має SharedFolder бути . Це ім'я буде видно іншим серверам. Додайте SharedUser дозволи.

Everyone Видаліть існуючі .

Підтвердьте за допомогою дозволу «Змінити».

Оскільки ми додали лише права доступу, доступ до яких можна отримати ззовні, ми встановимо їх на внутрішньому SharedUser рівні, щоб вони могли працювати в цій папці.

Підтвердьте за допомогою дозволу «Змінити».

Створіть файл для перевірки операції. У цій програмі кодування обробляється в UFT-8, тому, будь ласка, збережіть його в UTF-8.

Це нормально, якщо ви можете отримати доступ до Провідника з \\<サーバー名>\ іншого комп'ютера, увійтиSharedUser за допомогою та переглянути файл.

Створення програми для читання та запису файлів зі спільної папки програми ASP.NET Core

Операція Mr./Ms. полягає в тому, щоб натиснути кнопку.

  • Завантаження файлів у спільну папку та відображення їх на екрані
  • Запис нового файлу до спільної папки

процес.

Прикладами цього є Razor Pages і код MVC, але програма, яка отримує доступ до спільної папки, однакова для обох. Те ж саме стосується і веб-API. У всякому разі, він повинен працювати і в клієнтській програмі.

Процес, який підключається до мережі на час певного процесу

Створіть наступний код у будь-якому місці вашого проекту. Ім'я класу , SharedFolderAccessor але ім'я довільне. SharedFolderAccessor Ви можете отримати доступ до спільної папки, доки не створите Dispose екземпляр . using Надає вам змогу вказати проміжок часу, протягом якого можна отримати доступ до доступу у явній області.

using System.ComponentModel;
using System.Net;
using System.Runtime.InteropServices;

/// <summary>
/// 共有フォルダにユーザー名とパスワードでアクセスするためのクラスです。
/// using を使用すればそのスコープの間、共有フォルダにアクセスできます。
/// </summary>
public class SharedFolderAccessor : IDisposable
{
  private readonly string _networkName;

  /// <summary>
  /// コンストラクタです。
  /// </summary>
  /// <param name="networkName">共有フォルダのあるサーバーを「\\&lt;サーバー名&gt;」形式で指定します。</param>
  /// <param name="credentials">共有フォルダにアクセスするための資格情報です。</param>
  /// <exception cref="Win32Exception"></exception>
  public SharedFolderAccessor(string networkName, NetworkCredential credentials)
  {
    _networkName = networkName;

    // 接続するネットワークの情報を設定
    var netResource = new NetResource
    {
      Scope = ResourceScope.GlobalNetwork,
      ResourceType = ResourceType.Disk,
      DisplayType = ResourceDisplaytype.Share,
      RemoteName = networkName,
    };

    // ドメインがある場合はドメイン名も指定、ない場合はユーザー名のみ
    var userName = string.IsNullOrEmpty(credentials.Domain)
        ? credentials.UserName
        : $@"{credentials.Domain}\{credentials.UserName}";

    // 共有フォルダにユーザー名とパスワードで接続
    var result = WNetAddConnection2(netResource, credentials.Password, userName, 0);

    if (result != 0)
    {
      throw new Win32Exception(result, $"共有フォルダに接続できませんでした。(エラーコード:{result})");
    }

    // 正常に接続できれば WNetCancelConnection2 を呼び出すまではプログラムで共有フォルダにアクセス可能
  }

  ~SharedFolderAccessor()
  {
    // Dispose を呼び忘れたときの保険
    WNetCancelConnection2(_networkName, 0, true);
  }

  public void Dispose()
  {
    WNetCancelConnection2(_networkName, 0, true);
    GC.SuppressFinalize(this);  // Dispose を明示的に呼んだ場合はデストラクタの処理は不要
  }

  /// <summary>
  /// ネットワーク リソースへの接続を確立し、ローカル デバイスをネットワーク リソースにリダイレクトできます。
  /// </summary>
  /// <param name="netResource">ネットワーク リソース、ローカル デバイス、ネットワーク リソース プロバイダーに関する情報など。</param>
  /// <param name="password">ネットワーク接続の作成に使用するパスワード。</param>
  /// <param name="username">接続を確立するためのユーザー名。</param>
  /// <param name="flags">接続オプションのセット。</param>
  /// <returns></returns>
  [DllImport("mpr.dll")]
  private static extern int WNetAddConnection2(NetResource netResource, string password, string username, int flags);

  /// <summary>
  /// 既存のネットワーク接続を取り消します。
  /// </summary>
  /// <param name="name">リダイレクトされたローカル デバイスまたは切断するリモート ネットワーク リソースの名前。</param>
  /// <param name="flags">接続の種類。</param>
  /// <param name="force">接続に開いているファイルまたはジョブがある場合に切断を行う必要があるかどうか。</param>
  /// <returns></returns>
  [DllImport("mpr.dll")]
  private static extern int WNetCancelConnection2(string name, int flags, bool force);

  /// <summary>
  /// NETRESOURCE 構造体を定義しています。
  /// </summary>
  [StructLayout(LayoutKind.Sequential)]
  private class NetResource
  {
    public ResourceScope Scope;
    public ResourceType ResourceType;
    public ResourceDisplaytype DisplayType;
    public int Usage;
    public string LocalName = "";
    public string RemoteName = "";
    public string Comment = "";
    public string Provider = "";
  }

  /// <summary>
  /// ネットワークリソースのスコープ。
  /// </summary>
  private enum ResourceScope : int
  {
    /// <summary>ネットワークリソースへの現在の接続。</summary>
    Connected = 1,
    /// <summary>すべてのネットワークリソース。</summary>
    GlobalNetwork = 2,
    Remembered = 3,
    Recent = 4,
    /// <summary>ユーザーの現在および既定のネットワークコンテキストに関連付けられているネットワークリソース。</summary>
    Context = 5,
  };

  /// <summary>
  /// リソースの種類。
  /// </summary>
  private enum ResourceType : int
  {
    /// <summary>印刷リソースとディスクリソースの両方のコンテナー、または印刷またはディスク以外のリソースなど。</summary>
    Any = 0,
    /// <summary>共有ディスクボリューム。</summary>
    Disk = 1,
    /// <summary>共有プリンター。</summary>
    Print = 2,
    Reserved = 8,
  }

  /// <summary>
  /// ユーザーインターフェイスで使用する必要がある表示の種類。
  /// </summary>
  private enum ResourceDisplaytype : int
  {
    /// <summary>リソースの種類を指定しないネットワークプロバイダーによって使用されます。</summary>
    Generic = 0x0,
    /// <summary>サーバーのコレクション。</summary>
    Domain = 0x01,
    /// <summary>サーバー。</summary>
    Server = 0x02,
    /// <summary>共有ポイント。</summary>
    Share = 0x03,
    File = 0x04,
    Group = 0x05,
    /// <summary>ネットワークプロバイダー。</summary>
    Network = 0x06,
    Root = 0x07,
    Shareadmin = 0x08,
    /// <summary>ディレクトリ。</summary>
    Directory = 0x09,
    Tree = 0x0a,
    Ndscontainer = 0x0b,
  }
}

Оскільки він використовує API Win32 і WNetAddConnection2 WNetCancelConnection2 , він працює тільки в середовищі Windows. Поки що у мене є коментар, але якщо ви хочете дізнатися більше, будь ласка, пошукайте його в Інтернеті. Крім загальних папок, можна також виконувати операції по доступу до мережевих ресурсів.

Він простий у використанні, і якщо ви напишете наступне, ви using зможете отримати доступ до спільної папки під час видимості.

using (new SharedFolderAccessor($@"\\{serverName}", credentials))
{
  // この間は共有フォルダにアクセスできる
}

Однак насправді WNetCancelConnection2 з'єднання не відразу відключається в момент виклику , тому using ви можете отримати доступ до загальної папки навіть після прицілу.

Тестування коду за допомогою SharedFolderAccessor

Оскільки процес доступу до загальної папки не залежить від фреймворку, ми створюємо загальний метод тестування, який читає та записує файли. Pazor Pages і MVC слід називати однаково.

Вміст — це процес, який записує текст, переданий аргументу до спільної папки, читає текстовий файл, який уже міститься у спільній папці, і повертає текст.

using System.Net;

public static class Util
{
  public static string ReadAndWrite(string text)
  {
    var serverName = "ServerName";
    var folderName = "SharedFolder";
    var inputFileName = "Input.txt";
    var outputFileName = "Output.txt";
    var username = "SharedUser";
    var password = "password";

    var credentials = new NetworkCredential(username, password);
    using (new SharedFolderAccessor($@"\\{serverName}", credentials))
    {
      // ファイルの書き出し
      System.IO.File.WriteAllText(Path.Combine($@"\\{serverName}\{folderName}", outputFileName), text);

      // ファイルの読み込み
      return System.IO.File.ReadAllText(Path.Combine($@"\\{serverName}\{folderName}", inputFileName));
    }
  }
}

Сторінки бритви

У Razor Pages ми розміщуємо кнопку в Index.cshtml, натискаємо її, запускаємо тестовий код і виводимо результати на екран. У деяких випадках спільна папка може бути недоступною, тому її вкладають у спробу.

Index.cshtml.cs

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace SharedFolderAccessRazorPages.Pages
{
  public class IndexModel : PageModel
  {
    private readonly ILogger<IndexModel> _logger;
    public string Message { get; set; } = "";

    public IndexModel(ILogger<IndexModel> logger)
    {
      _logger = logger;
    }

    public void OnPost()
    {
      try
      {
        Message = Util.ReadAndWrite($"プログラムからの書き込み ({DateTime.Now})");
      }
      catch (Exception ex)
      {
        Message = ex.ToString();
      }
    }
  }
}

Index.cshtml

@page
@model IndexModel
@{
  ViewData["Title"] = "Home page";
}

<div class="text-center">
  <h1 class="display-4">Welcome</h1>
  <p>Learn about <a href="https://learn.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

@* ここから追加 *@
<form method="post">
  <button type="submit">サブミット</button>
</form>

<div>
  @Model.Message
</div>
@* ここまで追加 *@

MVC

Аналогічно у випадку з MVC Index.cshtml кнопка розміщується в , а при натисканні викликає тестовий код загальної папки.

Контролери/HomeController.cs

// 省略

namespace SharedFolderAccessMvc.Controllers
{
  public class HomeController : Controller
  {
    // 省略

    public IActionResult Index()
    {
      return View();
    }

    // ここから追加
    [HttpPost]
    public IActionResult Index(string dummy)
    {
      try
      {
        ViewData["Message"] = Util.ReadAndWrite($"プログラムからの書き込み ({DateTime.Now})");
      }
      catch (Exception ex)
      {
        ViewData["Message"] = ex.ToString();
      }
      return View();
    }
    // ここまで追加

    public IActionResult Privacy()
    {
      return View();
    }

    // 省略
  }
}

Index.cshtml

@{
  ViewData["Title"] = "Home Page";
}

<div class="text-center">
  <h1 class="display-4">Welcome</h1>
  <p>Learn about <a href="https://learn.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

@* ここから追加 *@
<form method="post">
  <button type="submit">サブミット</button>
</form>

<div>
  @ViewData["Message"]
</div>
@* ここまで追加 *@

Підтвердження роботи

Налагодьте та переконайтеся, що ви можете отримати доступ до спільної папки.

Побудова сервера додатків

Оскільки ми підтвердили, що доступ до спільної папки можна отримати, запустивши програму, наступний крок не потрібен. Якщо ви хочете перевірити операцію на сервері IIS, ви можете зробити це, виконавши наведені нижче дії.

Звідси це доповнення, тому я не буду пояснювати його занадто детально, а в основному поясню зображення.

Інсталяція IIS

Встановіть його за замовчуванням з диспетчера серверів. Не буду вдаватися в подробиці процедури.

Ніяких додаткових функцій не потрібно.

Наразі додаткові служби IIS не потрібні.

ASP.NET Встановлення пакета хостингу Core Runtime

Оскільки ми використовуємо ASP.NET Core 8, нам потрібно відповідно встановити середовище виконання. Завантажте його за такою URL-адресою:

Для того, щоб запустити ASP.NET Core в IIS, вам потрібно щось під назвою "Hosting Bundle". Завантажте "Hosting Bundle" з ASP.NET Core Runtime.

Після завантаження запустіть його на сервері.

Дотримуйтесь інструкцій майстра, щоб встановити його.

Опублікуйте свою програму

Виведіть програму, яку потрібно розгорнути в службі IIS, у вигляді файлу з Visual Studio.

Змініть його для Windows.

Опублікуйте, коли закінчите.

Якщо ви натиснете на цільове розташування, ви зможете відкрити папку, в якій знаходиться опублікований файл.

Вам не обов'язково приносити їх усі, але якщо ви не впевнені, ви можете взяти їх усі. На цьому етапі все, що вам потрібно зробити, це переконатися, що файл існує.

Створення та розгортання веб-додатків

У засобі адміністрування Windows відкрийте диспетчер інформаційних служб Інтернету (IIS).

Ми створимо сайт, але цього разу ми будемо використовувати "Веб-сайт за замовчуванням", який є там з самого початку.

Вибравши параметр Веб-сайт за промовчанням, натисніть кнопку Провідник, щоб відкрити папку. Скопіюйте опубліковану програму сюди. Вихідний файл можна видалити.

Відкрийте сторінку за посиланням IIS і подивіться, чи з'явиться екран. Ви можете спочатку відкрити веб-браузер і ввести URL-адресу безпосередньо.

Підтвердження роботи

Натисніть кнопку, щоб переконатися, що він працює без будь-яких проблем. У наведеному вище пункті доступ до нього здійснюється з веб-сервера, але оскільки це веб-сервер, ним має бути можливість керувати з інших ПК.