.NET MAUI Blazor로 AD 비밀번호 변경 데스크톱 애플리케이션 작성 (Web API 연동)

  完成了《AD 密碼驗證》與《AD 密碼修改》兩個 API 後接下來用 .NET MAUI Blazor 來寫桌面端的程式稍微瞭解了 Blazor 後覺得好神奇感覺就是把網頁塞進應用程式裡面,실행 중에도 '작업 관리자'에서 뒤에서 Edge 관련 구성 요소가 실행되고 있는 것을 볼 수 있습니다,그리고 F12를 누르면 개발자 도구 창도 열립니다! 다만 이것 때문에 약간 보안에 대한 의문이 생기기도 했습니다。하지만 전체적으로 느껴지는 감각은 여전히 꽤 독특합니다,마침 제가 웹 문법에 좀 익숙해서,Razor와 함께 UI 화면을 설계하며,훨씬 친근하게 느껴집니다。

  程式的結構是兩個頁面第一個頁面是 AD 密碼驗證通過後才會導到 AD 密碼變更頁面

프로젝트 템플릿

  • .NET MAUI Blazor 應用程式

《套件》

  • bootstrap

Services/PasswordManagementService.cs

using System.Net.Http.Json;

namespace NTool.Services
{
    public class PasswordManagementService(HttpClient httpClient)
    {
        public async Task<bool> ValidateAsync(string username, string password)
        {
            var request = new { Username = username, Password = password };
            var response = await httpClient.PostAsJsonAsync("Password/Validate", request);

            return response.IsSuccessStatusCode;
        }

        public async Task<bool> ChangeAsync(string username, string password, string newPassword)
        {
            var request = new { Username = username, OldPassword = password, NewPassword = newPassword };
            var response = await httpClient.PostAsJsonAsync("Password/ChangeSdsP", request);

            return response.IsSuccessStatusCode;
        }
    }
}

Components/Pages/PasswordValidation.razor

@page "/"
@using NTool.Services
@using NTool.Models
@inject PasswordManagementService PasswordManagementService
@inject ValidRequest ValidRequest
@inject NavigationManager Navigation

<h3 class="mt-5 text-center">AD 密碼變更工具</h3>
<p>請驗證帳號密碼</p>

<EditForm Model="ValidRequest" OnValidSubmit="HandleValidSubmit">
	<DataAnnotationsValidator />
	<ValidationSummary />

	<div>
		<label for="username">使用者登入名稱</label>
		<InputText id="username" @bind-Value="ValidRequest.Username" placeholder="輸入帳號" />
	</div>
	<div>
		<label for="password">密碼</label>
		<InputText id="password" @bind-Value="ValidRequest.Password" placeholder="輸入密碼" type="password" />
	</div>
	<button type="submit">驗證</button>
</EditForm>

<p>@resultMessage</p>

@code {
	private string resultMessage = string.Empty;

	private async Task HandleValidSubmit()
	{
		var isValid = await PasswordManagementService.ValidateAsync(ValidRequest.Username, ValidRequest.Password);
		if (isValid)
		{
			Navigation.NavigateTo("/PasswordChange");
		}
		else
		{
			resultMessage = "驗證失敗。";
		}
	}
}

Components/Pages/PasswordChange.razor

@page "/PasswordChange"
@using NTool.Models
@using NTool.Services
@inject PasswordManagementService PasswordManagementService
@inject HttpClient Http
@inject NavigationManager Navigation
@inject ChangeRequest ChangeRequest
@inject ValidRequest ValidRequest

<h3 class="mt-5 text-center">AD 密碼變更工具</h3>
<p>@Message</p>

<EditForm Model="ChangeRequest" OnValidSubmit="HandleChangeSubmit">
    <DataAnnotationsValidator />
    <ValidationSummary />

    <div>
        <label for="newPassword">新密碼</label>
        <InputText id="newPassword" @bind-Value="ChangeRequest.NewPassword" placeholder="輸入新密碼" type="password" />
    </div>
    <div>
        <label for="confirmPassword">確認新密碼</label>
        <InputText id="confirmPassword" @bind-Value="ChangeRequest.ConfirmPassword" placeholder="確認新密碼" type="password" />
    </div>
    <button type="submit">變更密碼</button>
</EditForm>

@code {
    private string Message { get; set; } = "驗證成功!請變更密碼";

    private async Task HandleChangeSubmit()
    {

        var isValid = await PasswordManagementService.ChangeAsync(ValidRequest.Username, ValidRequest.Password, ChangeRequest.NewPassword);
        if (isValid)
        {
            Message = "密碼變更成功。";
            ValidRequest.Password = string.Empty;
            ChangeRequest.NewPassword = string.Empty;
            ChangeRequest.ConfirmPassword = string.Empty;
            // Navigation.NavigateTo("/");
        }
        else
        {
            Message = "密碼變更失敗。";
            ChangeRequest.NewPassword = string.Empty;
            ChangeRequest.ConfirmPassword = string.Empty;
        }
    }
}

Models/PasswordModel.cs

using System.ComponentModel.DataAnnotations;

namespace NTool.Models
{
    public class ValidRequest
    {
        [Required(ErrorMessage = "[使用者登入名稱] 為必填欄位。")]
        public required string Username { get; set; }

        [Required(ErrorMessage = "[密碼] 為必填欄位。")]
        public required string Password { get; set; }
    }    
    
    public class ChangeRequest
    {
        [Required(ErrorMessage = "[新密碼] 為必填欄位。")]
        public required string NewPassword { get; set; }

        [Required(ErrorMessage = "[確認新密碼] 為必填欄位。")]
        [Compare("NewPassword", ErrorMessage = "[新密碼] 與 [確認新密碼] 不相符。")]
        public required string ConfirmPassword { get; set; }
    }
}

MauiProgram.cs

using Microsoft.Extensions.Logging;
using NTool.Services;
using NTool.Models;

namespace NTool
{
    public static class MauiProgram
    {
        public static MauiApp CreateMauiApp()
        {
            var builder = MauiApp.CreateBuilder();
            builder
                .UseMauiApp<App>()
                .ConfigureFonts(fonts =>
                {
                    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                });

            builder.Services.AddMauiBlazorWebView();

#if DEBUG
    		builder.Services.AddBlazorWebViewDeveloperTools();
    		builder.Logging.AddDebug();
#endif
            // 注入 HttpClient,並設定 API 的基底網址
            builder.Services.AddScoped(sp => new HttpClient
            {
                BaseAddress = new Uri("https://api.abc.com/ad/")
            });

            // 注入 Services、Models
            builder.Services.AddScoped<PasswordManagementService>();
            builder.Services.AddScoped<ValidRequest>();
            builder.Services.AddScoped<ChangeRequest>();

            return builder.Build();
        }
    }
}

wwwroot/css/styles.css

body {
    background-color: #f0f8ff; /* 淡粉藍背景色 */
    font-family: Arial, sans-serif;
    margin: 0;
    padding: 0;
}

form {
    max-width: 400px;
    margin: 50px auto;
    background: white;
    border-radius: 8px;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
    padding: 20px;
}

    form div {
        margin-bottom: 15px;
    }

    form label {
        display: block;
        font-weight: bold;
        margin-bottom: 5px;
    }

    form input {
        width: 100%;
        padding: 8px;
        border: 1px solid #ccc;
        border-radius: 4px;
    }

    form button {
        width: 100%;
        padding: 10px;
        background-color: #4caf50;
        color: white;
        border: none;
        border-radius: 4px;
        font-size: 16px;
        cursor: pointer;
    }

        form button:hover {
            background-color: #45a049;
        }

p {
    text-align: center;
    color: #ff0000;
    font-weight: bold;
}

《結果畫面》

댓글 남기기

이메일 주소는 게시되지 않습니다. 필수 항목 표시 *

이 사이트는 Akismet을 사용하여 스팸을 줄입니다. 댓글 데이터 처리 방법 알아보기.