MAUI 嵌入式 Web 架构实战(六) Web Admin 权限系统与登录认证
MAUI 嵌入式 Web 架构实战(六)
PicoServer Web Admin 权限系统设计与认证架构
源码地址:
https://github.com/densen2014/MauiPicoAdmin
在前几篇文章中,我们已经逐步构建了一个完整的 PicoServer 本地 Web Admin 系统:
- 路由机制
- REST API 架构
- 静态文件托管
- Web Admin 管理后台
至此,我们已经拥有:
Web UI
↓
REST API
↓
业务服务
但对于任何一个真实系统来说,还缺少一个最关键的部分:
身份认证与权限控制(Auth System)
如果没有权限系统:
- 任意用户都可以访问管理后台
- 所有 API 都可以被直接调用
- 整个系统没有安全边界
因此,本篇我们将设计一套:
适用于 PicoServer 的完整认证与权限架构
并实现:
- 登录认证
- Token 机制
- API 权限保护
- 角色权限模型
- API 过滤器
- 权限注解机制
最终构建出一个 可扩展的权限系统框架。
一、权限系统架构设计
在 Web 系统中,权限系统通常包含三个层级:
Authentication
身份认证
Authorization
权限控制
Permission Model
权限模型
其关系如下:
用户登录
↓
获取 Token
↓
API 请求携带 Token
↓
服务器验证 Token
↓
检查用户权限
↓
允许 / 拒绝访问
二、整体架构设计
在 PicoServer 中,我们设计如下架构:
Web Admin UI
│
│ fetch API
▼
┌───────────────────┐
│ PicoServer │
│ │
│ Auth Middleware │
│ │ │
│ ▼ │
│ Permission Filter │
│ │ │
│ ▼ │
│ Controller │
│ │ │
│ ▼ │
│ Service Layer │
└───────────────────┘
核心思想:
所有 API 请求先经过认证中间件。
三、Token 认证机制
在本地 Web Admin 系统中,推荐使用 Token 认证。
原因:
- 不依赖浏览器 Session
- 适合 REST API
- 前端调用简单
- 实现成本低
认证流程:
用户登录
↓
服务器生成 Token
↓
前端保存 Token
↓
每次 API 请求携带 Token
↓
服务器验证 Token
四、实现登录接口
首先实现登录 API:
POST /api/login
请求:
{
"username":"admin",
"password":"123456"
}
登录接口实现
public class LoginController
{
public async Task Login(HttpListenerRequest request, HttpListenerResponse response)
{
var body = await new StreamReader(request.InputStream).ReadToEndAsync();
var login = JsonSerializer.Deserialize<LoginRequest>(body, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
if (login != null && login.Username == "admin" && login.Password == "123456")
{
var token = TokenService.GenerateToken(login.Username);
await response.WriteJsonAsync(new
{
success = true,
token = token
});
}
else
{
response.StatusCode = 401;
await response.WriteJsonAsync(new
{
success = false,
message = "Invalid username or password"
});
}
}
public class LoginRequest
{
public string? Username { get; set; }
public string? Password { get; set; }
}
}
- 文章第三篇 HttpHelper 工具修正
之前写的有bug, 未能正确设置 contentType , 修正如下, 命名由 WriteJson 改为 WriteJsonAsync
public static class HttpHelper
{
public static async Task WriteJsonAsync(HttpListenerResponse response, object obj)
{
string json = JsonSerializer.Serialize(obj);
await response.WriteAsync(json, contentType: "application/json");
}
}
五、Token 服务设计
为了管理 Token,我们创建一个 TokenService:
public class TokenService
{
static Dictionary<string,UserSession> sessions = new();
public static string GenerateToken(string username)
{
var token = Guid.NewGuid().ToString();
sessions[token] = new UserSession
{
Username = username,
Role = "admin",
ExpireTime = DateTime.Now.AddHours(12)
};
return token;
}
public static UserSession Validate(string token)
{
if(!sessions.ContainsKey(token))
return null;
var session = sessions[token];
if(session.ExpireTime < DateTime.Now)
return null;
return session;
}
}
Session 数据结构:
public class UserSession
{
public string? Username { get; set; }
public string? Role { get; set; }
public DateTime ExpireTime { get; set; }
}
六、认证中间件(Auth Middleware)
为了避免在每个 API 手动验证 Token,我们设计一个:
统一认证中间件
所有 API
↓
Auth Middleware
↓
Controller
实现:
public class AuthMiddleware
{
public static UserSession? Authenticate(HttpListenerRequest request)
{
var token = request.Headers["Authorization"];
if (string.IsNullOrEmpty(token))
return null;
return TokenService.Validate(token);
}
}
七、API Filter 机制
进一步,我们可以增加一个 API Filter。
作用:
- 自动拦截未授权访问
- 统一返回错误
示例:
public static async Task<bool> RequireAuth(
HttpListenerRequest request,
HttpListenerResponse response)
{
var session = AuthMiddleware.Authenticate(request);
if(session == null)
{
response.StatusCode = 401;
await response.WriteJsonAsync(new
{
message = "Unauthorized"
});
return false;
}
return true;
}
八、保护 API 接口
现在 API 可以这样写:
public async Task GetUserList(HttpListenerRequest request, HttpListenerResponse response)
{
if(!await RequireAuth(request,response))
return;
var users = new[]
{
new { id = 1, name = "admin" },
new { id = 2, name = "operator" }
};
await response.WriteJsonAsync(users);
}
这样所有 API 都会自动保护。
九、权限模型设计
当系统复杂后,需要引入 角色权限模型。
经典模型:
User
↓
Role
↓
Permission
例如:
User
├─ admin
└─ operator
Role
├─ admin
└─ viewer
Permission
├─ product.view
├─ product.edit
└─ order.manage
API 可以定义权限:
/api/product/list
/api/product/create
/api/order/delete
服务器通过角色判断是否允许访问。
十、权限注解设计(高级架构)
更高级的设计是:
权限注解(Attribute)
例如:
[RequirePermission("product.view")]
public async Task ProductList()
{
}
Attribute 定义:
public class RequirePermissionAttribute : Attribute
{
public string Permission { get; }
public RequirePermissionAttribute(string permission)
{
Permission = permission;
}
}
在 API 执行前:
- 读取 Attribute
- 判断权限
- 自动拦截
这就是很多 Web 框架使用的机制:
- ASP.NET Core
- Spring Boot
- NestJS
十一、完整权限系统架构
最终系统结构:
MAUI App
│
├── WebView
│
└── PicoServer
│
├── Static File Server
│
├── REST API
│
├── Auth Middleware
│
├── Permission Filter
│
└── Service Layer
优势:
- 无服务器部署
- 本地运行
- 高性能
- 跨平台
十二、其他代码
因篇幅有限, 部分代码并未完整贴出, 请参考工程同步源码: https://github.com/densen2014/MauiPicoAdmin
最终 RegisterRoutes
private void RegisterRoutes()
{
var demo = new DemoController();
var product = new ProductController();
var login = new LoginController();
var user = new UserController();
api.AddStaticFiles("/", wwwrootPath);
api.AddRoute("/api/hello", demo.Hello);
api.AddRoute("/api/time", demo.GetTime);
api.AddRoute("/api/status", demo.GetStatus);
api.AddRoute("/api/product/list", product.List);
api.AddRoute("/api/product/detail", product.Detail);
api.AddRoute("/api/login", login.Login);
api.AddRoute("/api/user/list", user.GetUserList);
}
添加测试文件 api_test.http
相关说明 https://aka.ms/vs/httpfile
# For more info on HTTP files go to https://aka.ms/vs/httpfile
@hostname=127.0.0.1
### Hello
GET http://{{hostname}}:8090/api/hello
### Time
GET http://{{hostname}}:8090/api/time
### Status
GET http://{{hostname}}:8090/api/status
### Product List
GET http://{{hostname}}:8090/api/product/list
### Product Detail
GET http://{{hostname}}:8090/api/product/detail?id=1
### Login
### 通过变量和脚本自动提取上一个请求的响应内容,并在下一个请求中复用
# @name login
POST http://{{hostname}}:8090/api/login
Content-Type: application/json
{
"username": "admin",
"password": "123456"
}
### User List (with token)
GET http://{{hostname}}:8090/api/user/list
Authorization: {{login.response.body.$.token}}
# Response
十三、本篇总结
在本篇文章中,我们构建了一套完整的 PicoServer 权限系统架构:
实现了:
- 登录认证 API
- Token 机制
- API 权限保护
- Auth Middleware
- API Filter
- 角色权限模型
- 权限注解架构
至此,我们的系统已经具备:
企业级 Web Admin 基础架构
下一篇预告
接下来我们将继续升级系统能力:
MAUI 嵌入式 Web 架构实战(七)
本地数据库与数据持久化
我们将实现:
- SQLite 数据库
- ORM 数据访问
- 商品 CRUD API
- Admin 数据管理
- 本地数据同步
最终实现:
一个完整可用的本地管理系统。
关联项目
FreeSql QQ群:4336577
BA & Blazor QQ群:795206915
Maui Blazor 中文社区 QQ群:645660665
知识共享许可协议
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名AlexChow(包含链接: https://github.com/densen2014 ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系 。
转载声明
本文来自博客园,作者:周创琳 AlexChow,转载请注明原文链接:https://www.cnblogs.com/densen2014/p/19674457
AlexChow
今日头条 | 博客园 | 知乎 | Gitee | GitHub


浙公网安备 33010602011771号