MiniAuth 一個輕量 ASP.NET Core Identity Web 後臺管理中間外掛
「一行程式碼」為「新、舊專案」 新增 Identity 系統跟使用者、許可權管理網頁後臺系統
開箱即用,避免打掉重寫或是嚴重耦合情況
Github: https://github.com/mini-software/MiniAuth , Gitee: https://gitee.com/shps951023/MiniAuth
特點
- 相容 : 支援 .NET identity Based on JWT, Cookie, Session 等
- 簡單 : 拔插設計,API、SPA、MVC、Razor Page 等開箱即用
- 支援多資料庫 : 支援 Oracle, SQL Server, MySQL 等 EF Core
- 非侵入式 : 不影響現有資料庫、專案結構
- 多平臺 : 支援 Linux, macOS 環境
安裝
從 NuGet 安裝套件
快速開始
在 Startup 新增一行程式碼 services.AddMiniAuth()
並執行專案,例子:
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMiniAuth(); // <= ❗❗❗
var app = builder.Build();
app.Run();
}
}
接著訪問管理網頁,Link 為 http(s)://yourhost/miniauth/index.html
,預設 admin 管理賬號為 admin@mini-software.github.io
密碼為 E7c4f679-f379-42bf-b547-684d456bc37f
(請記得修改密碼),即可管理你的 Identity 使用者、角色、端點。
在需要許可權管理的類別或方法上加上 [Authorize]
或是角色管控 [Authorize(Roles = "角色")]
,假設沒登入返回 401 狀態, 沒許可權返回 403 狀態。
MiniAuth Cookie Identity
MiniAuth 預設為單體 Coookie Based identity,如前後端分離專案請更換 JWT 等 Auth。
MiniAuth JWT Identity
只需要簡單指定 AuthenticationType 為 BearerJwt
builder.Services.AddMiniAuth(options:(options) =>
{
options.AuthenticationType = MiniAuthOptions.AuthType.BearerJwt;
});
請記得自定義 JWT Security Key,如:
builder.Services.AddMiniAuth(options: (options) =>
{
options.JWTKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("6ee3edbf-488e-4484-9c2c-e3ffa6dcbc09"));
});
獲取使用者 token 方式
前端 Javascript XHR 例子
var data = JSON.stringify({
"username": "admin@mini-software.github.io",
"password": "E7c4f679-f379-42bf-b547-684d456bc37f",
"remember": false
});
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function() {
if(this.readyState === 4) {
console.log(this.responseText);
}
});
xhr.open("POST", "http://yourhost/miniauth/login");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(data);
返回結果
{
"ok": true,
"code": 200,
"message": null,
"data": {
"tokenType": "Bearer",
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiIxZTIxOGY4My1iZjE3LTRhY2YtODhmOS1iOTQ3NjhjOWUwMGMiLCJuYW1lIjoiYWRtaW5AbWluaS1zb2Z0d2FyZS5naXRodWIuaW8iLCJyb2xlIjoibWluaWF1dGgtYWRtaW4iLCJzdWIiOiJhZG1pbkBtaW5pLXNvZnR3YXJlLmdpdGh1Yi5pbyIsIm5iZiI6MTcxODIwNDg5NSwiZXhwIjoxNzE4MjA1Nzk1LCJpYXQiOjE3MTgyMDQ4OTUsImlzcyI6Ik1pbmlBdXRoIn0._-DQ_rcbeju8_nrK2lD5we0rre04_xdDZNF6NhM0Rg0",
"expiresIn": 900
}
}
將 accessToken 儲存在 localstorage 或是 cookie 內,呼叫你的 [Authorize] api 時設定 Header Authorization : Bearer + 空格 + accessToken
,系統會自動驗證。
舉例:
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function() {
if(this.readyState === 4) {
console.log(this.responseText);
}
});
xhr.open("GET", "http://yourhost:5014/your/api");
xhr.setRequestHeader("Authorization", "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiIxZTIxOGY4My1iZjE3LTRhY2YtODhmOS1iOTQ3NjhjOWUwMGMiLCJuYW1lIjoiYWRtaW5AbWluaS1zb2Z0d2FyZS5naXRodWIuaW8iLCJyb2xlIjoibWluaWF1dGgtYWRtaW4iLCJzdWIiOiJhZG1pbkBtaW5pLXNvZnR3YXJlLmdpdGh1Yi5pbyIsIm5iZiI6MTcxODIwNDg5NSwiZXhwIjoxNzE4MjA1Nzk1LCJpYXQiOjE3MTgyMDQ4OTUsImlzcyI6Ik1pbmlBdXRoIn0._-DQ_rcbeju8_nrK2lD5we0rre04_xdDZNF6NhM0Rg0");
xhr.send();
設定過期時間
options.TokenExpiresIn = 30 * 60;
單位為秒,預設30分鐘,另外注意 .NET JWT ClockSkew JwtBearerOptions 預設要額外加上5分鐘 原因
重新整理 Refresh Token API (JWT)
API : /MiniAuth/refreshToken
Body:
{
"refreshToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxZTIxOGY4My1iZjE3LTRhY2YtODhmOS1iOTQ3NjhjOWUwMGMiLCJuYmYiOjE3MTg1MjIxOTEsImV4cCI6MTcxODUyMzk5MSwiaWF0IjoxNzE4NTIyMTkxLCJpc3MiOiJNaW5pQXV0aCJ9.HYBWrM2suDiM4OG0FSlXhNgktZIG9l3ufmIAnwZiIoU"
}
Header:
Authorization:Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiYWRtaW5AbWluaS1zb2Z0d2FyZS5naXRodWIuaW8iLCJyb2xlIjoibWluaWF1dGgtYWRtaW4iLCJzdWIiOiIxZTIxOGY4My1iZjE3LTRhY2YtODhmOS1iOTQ3NjhjOWUwMGMiLCJuYmYiOjE3MTg1MjIxOTEsImV4cCI6MTcxODUyNTc5MSwiaWF0IjoxNzE4NTIyMTkxLCJpc3MiOiJNaW5pQXV0aCJ9.rgAgsziAdLqOC9NYra-M9WQl8BJ99sRdfzRKNkMz9dk
過期時間為 MiniAuthOptions.TokenExpiresIn / 2
,預設30分鐘
設定、選項、自定義
預設模式
- MiniAuth 預設模式為IT Admin 集中使用者管理,使用者註冊、密碼重置等操作需要 Admin 許可權賬號操作,預設 Role = miniauth-admin
關閉 MiniAuth Login
如果你只想用自己的登入邏輯、頁面、API,可以指定登入路徑,關閉開關
// 放在 service 註冊之前
builder.Services.AddMiniAuth(options: (options) =>
{
options.LoginPath = "/Identity/Account/Login";
options.DisableMiniAuthLogin = true;
});
自定義預設的 SQLite Connection String
builder.Services.AddMiniAuth(options: (options) =>
{
options.SqliteConnectionString = "Data Source=miniauth_identity.db";
});
自定義資料庫、使用者、角色
MiniAuth 系統預設使用 SQLite EF Core、IdentityUser、IdentityRole開箱即用
如果需要切換請在 app.UseMiniAuth
泛型指定不同的資料庫、自己的使用者、角色類別。
app.UseMiniAuth<YourDbContext, YourIdentityUser, YourIdentityRole>();
登入、使用者驗證
非 ApiController 預設登入導向 login.html 頁面 (判斷方式Headers["X-Requested-With"] == "XMLHttpRequest" 或是 ApiControllerAttribute)
ApiController 的 Controller 預設不會導向登入頁面,而是返回 401 status code
自定義前端
- 管理後臺前端在
/src/Frontend_Identity
主體使用 Vue3 + Vite,使用 npm run build 後即可更新 miniauth 的 UI - 登入頁面不想使用 miniauth 預設, mvc可以使用 identity 自帶的Scaffolded Login.cshtml ,或是更改 miniauth 前端的 login.html, js, css
自定路由字首
builder.Services.AddMiniAuth(options: (options) =>
{
options.RoutePrefix = "YourName";
});
預設 RoutePrefix 為 MiniAuth
。
登入API (JWT)
API: /MiniAuth/login
Body:
{
"username":"admin@mini-software.github.io",
"password":"E7c4f679-f379-42bf-b547-684d456bc37f",
"remember":false
}
Response:
{
"ok": true,
"code": 200,
"message": null,
"data": {
"tokenType": "Bearer",
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiYWRtaW5AbWluaS1zb2Z0d2FyZS5naXRodWIuaW8iLCJyb2xlIjoibWluaWF1dGgtYWRtaW4iLCJzdWIiOiIxZTIxOGY4My1iZjE3LTRhY2YtODhmOS1iOTQ3NjhjOWUwMGMiLCJuYmYiOjE3MTg1MjIxOTEsImV4cCI6MTcxODUyNTc5MSwiaWF0IjoxNzE4NTIyMTkxLCJpc3MiOiJNaW5pQXV0aCJ9.rgAgsziAdLqOC9NYra-M9WQl8BJ99sRdfzRKNkMz9dk",
"expiresIn": 3600,
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxZTIxOGY4My1iZjE3LTRhY2YtODhmOS1iOTQ3NjhjOWUwMGMiLCJuYmYiOjE3MTg1MjIxOTEsImV4cCI6MTcxODUyMzk5MSwiaWF0IjoxNzE4NTIyMTkxLCJpc3MiOiJNaW5pQXV0aCJ9.HYBWrM2suDiM4OG0FSlXhNgktZIG9l3ufmIAnwZiIoU"
}
}
註冊
請使用 ASP.NET Core Identity 自帶的註冊API跟頁面
忘記密碼
請使用 ASP.NET Core Identity 自帶的註冊API跟頁面
獲取使用者資訊
請使用 ASP.NET Core Identity 自帶的註冊API跟頁面
注意事項
注意順序
請將 UseMiniAuth 放在路由生成之後,否則系統無法獲取路由資料作許可權判斷,如 :
app.UseRouting();
app.UseMiniAuth();
請新增 Role 規則
請新增 AddRoles<IdentityRole>()
,否則 [Authorize(Roles = "許可權")]
不會生效
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddRoles<IdentityRole>() // ❗❗❗
.AddEntityFrameworkStores<ApplicationDbContext>();
應用在現有的 identity 專案,自定義邏輯
把 AddMiniAuth autoUse 關閉,將 UseMiniAuth 並在泛型引數換上自己的 IdentityDBContext、使用者、許可權認證,放在自己的 Auth 之後,例子:
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddControllersWithViews();
builder.Services.AddMiniAuth(autoUse: false); // <= ❗❗❗
var app = builder.Build();
app.UseMiniAuth<ApplicationDbContext, IdentityUser, IdentityRole>(); // <= ❗❗❗
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
app.Run();
}
能切換使用自己的使用者、角色、DB、Identity 邏輯。
分散式系統
- 資料庫來源請換成 SQL Server、MySQL、PostgreSQL 等資料庫
- 建議更換 JWT 等 auth 方式