feat: backend add auth method
This commit is contained in:
parent
c6c3f1cc41
commit
d6167ac286
|
@ -1,9 +1,12 @@
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
using Microsoft.Extensions.FileProviders;
|
using Microsoft.Extensions.FileProviders;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NLog.Web;
|
using NLog.Web;
|
||||||
|
using NSwag.Generation.Processors.Security;
|
||||||
using server.Services;
|
using server.Services;
|
||||||
|
|
||||||
// Early init of NLog to allow startup and exception logging, before host is built
|
// Early init of NLog to allow startup and exception logging, before host is built
|
||||||
|
@ -38,6 +41,27 @@ try
|
||||||
options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
|
options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Add JWT Token Authorization
|
||||||
|
builder.Services
|
||||||
|
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||||
|
.AddJwtBearer(options =>
|
||||||
|
{
|
||||||
|
options.TokenValidationParameters = new TokenValidationParameters
|
||||||
|
{
|
||||||
|
ValidateIssuer = true,
|
||||||
|
ValidateAudience = true,
|
||||||
|
ValidateLifetime = true,
|
||||||
|
ValidateIssuerSigningKey = true,
|
||||||
|
RequireExpirationTime = true,
|
||||||
|
ValidIssuer = "dlut.edu.cn",
|
||||||
|
ValidAudience = "dlut.edu.cn",
|
||||||
|
IssuerSigningKey = new SymmetricSecurityKey(
|
||||||
|
Encoding.UTF8.GetBytes("my secret key 1234567890my secret key 1234567890")),
|
||||||
|
};
|
||||||
|
options.Authority = "http://localhost:5000";
|
||||||
|
options.RequireHttpsMetadata = false;
|
||||||
|
});
|
||||||
|
|
||||||
// Add CORS policy
|
// Add CORS policy
|
||||||
if (builder.Environment.IsDevelopment())
|
if (builder.Environment.IsDevelopment())
|
||||||
{
|
{
|
||||||
|
@ -59,7 +83,7 @@ try
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add Swagger
|
// Add Swagger
|
||||||
builder.Services.AddOpenApiDocument(options =>
|
builder.Services.AddSwaggerDocument(options =>
|
||||||
{
|
{
|
||||||
options.PostProcess = document =>
|
options.PostProcess = document =>
|
||||||
{
|
{
|
||||||
|
@ -81,8 +105,19 @@ try
|
||||||
// }
|
// }
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Authorization
|
||||||
|
options.AddSecurity("Bearer", new NSwag.OpenApiSecurityScheme
|
||||||
|
{
|
||||||
|
Description = "请输入token,格式为 Bearer xxxxxxxx(注意中间必须有空格)",
|
||||||
|
Name = "Authorization",
|
||||||
|
In = NSwag.OpenApiSecurityApiKeyLocation.Header,
|
||||||
|
Type = NSwag.OpenApiSecuritySchemeType.ApiKey,
|
||||||
|
});
|
||||||
|
options.OperationProcessors.Add(new OperationSecurityScopeProcessor("Bearer"));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// 添加 HTTP 视频流服务
|
// 添加 HTTP 视频流服务
|
||||||
builder.Services.AddSingleton<HttpVideoStreamService>();
|
builder.Services.AddSingleton<HttpVideoStreamService>();
|
||||||
builder.Services.AddHostedService(provider => provider.GetRequiredService<HttpVideoStreamService>());
|
builder.Services.AddHostedService(provider => provider.GetRequiredService<HttpVideoStreamService>());
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
<PackageReference Include="DotNext.Threading" Version="5.19.1" />
|
<PackageReference Include="DotNext.Threading" Version="5.19.1" />
|
||||||
<PackageReference Include="Honoo.IO.Hashing.Crc" Version="1.3.3" />
|
<PackageReference Include="Honoo.IO.Hashing.Crc" Version="1.3.3" />
|
||||||
<PackageReference Include="linq2db.AspNet" Version="5.4.1" />
|
<PackageReference Include="linq2db.AspNet" Version="5.4.1" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.7" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="9.0.4" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="9.0.4" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SpaProxy" Version="9.0.4" />
|
<PackageReference Include="Microsoft.AspNetCore.SpaProxy" Version="9.0.4" />
|
||||||
<PackageReference Include="Microsoft.OpenApi" Version="1.6.23" />
|
<PackageReference Include="Microsoft.OpenApi" Version="1.6.23" />
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
using Microsoft.AspNetCore.Cors;
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
|
||||||
namespace server.Controllers;
|
namespace server.Controllers;
|
||||||
|
|
||||||
|
@ -13,57 +17,70 @@ public class DataController : ControllerBase
|
||||||
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 创建数据库表
|
/// [TODO:description]
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>插入的记录数</returns>
|
/// <param name="name">[TODO:parameter]</param>
|
||||||
[EnableCors("Development")]
|
/// <param name="password">[TODO:parameter]</param>
|
||||||
[HttpPost("CreateTable")]
|
/// <returns>[TODO:return]</returns>
|
||||||
public IResult CreateTables()
|
[HttpPost("login")]
|
||||||
|
public IActionResult Login(string name, string password)
|
||||||
{
|
{
|
||||||
|
// 验证用户密码
|
||||||
using var db = new Database.AppDataConnection();
|
using var db = new Database.AppDataConnection();
|
||||||
db.CreateAllTables();
|
var ret = db.CheckUserPassword(name, password);
|
||||||
return TypedResults.Ok();
|
if (!ret.IsSuccessful) return StatusCode(StatusCodes.Status500InternalServerError);
|
||||||
|
if (!ret.Value.HasValue) return BadRequest($"TODO");
|
||||||
|
var user = ret.Value.Value;
|
||||||
|
|
||||||
|
// 生成 JWT
|
||||||
|
var tokenHandler = new JwtSecurityTokenHandler();
|
||||||
|
var key = Encoding.ASCII.GetBytes("my secret key 1234567890my secret key 1234567890");
|
||||||
|
var tokenDescriptor = new SecurityTokenDescriptor
|
||||||
|
{
|
||||||
|
Subject = new ClaimsIdentity(new Claim[]
|
||||||
|
{
|
||||||
|
new Claim(ClaimTypes.Name, user.Name),
|
||||||
|
new Claim(ClaimTypes.Email, user.EMail),
|
||||||
|
}),
|
||||||
|
Expires = DateTime.UtcNow.AddHours(1),
|
||||||
|
SigningCredentials = new SigningCredentials(
|
||||||
|
new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature),
|
||||||
|
Audience = "dlut.edu.cn",
|
||||||
|
Issuer = "dlut.edu.cn",
|
||||||
|
};
|
||||||
|
var token = tokenHandler.CreateToken(tokenDescriptor);
|
||||||
|
var jwt = tokenHandler.WriteToken(token);
|
||||||
|
|
||||||
|
return Ok(jwt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 删除数据库表
|
/// [TODO:description]
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>插入的记录数</returns>
|
/// <returns>[TODO:return]</returns>
|
||||||
[EnableCors("Development")]
|
[HttpGet("TestAuth")]
|
||||||
[HttpDelete("DropTables")]
|
[Authorize]
|
||||||
public IResult DropTables()
|
public IActionResult TestAuth()
|
||||||
{
|
{
|
||||||
using var db = new Database.AppDataConnection();
|
return Ok("Authenticated!");
|
||||||
db.DropAllTables();
|
|
||||||
return TypedResults.Ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取所有用户
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>用户列表</returns>
|
|
||||||
[HttpGet("AllUsers")]
|
|
||||||
public IResult AllUsers()
|
|
||||||
{
|
|
||||||
using var db = new Database.AppDataConnection();
|
|
||||||
var ret = db.User.ToList();
|
|
||||||
return TypedResults.Ok(ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 注册新用户
|
/// 注册新用户
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="name">用户名</param>
|
/// <param name="name">用户名</param>
|
||||||
|
/// <param name="email">[TODO:parameter]</param>
|
||||||
|
/// <param name="password">[TODO:parameter]</param>
|
||||||
/// <returns>操作结果</returns>
|
/// <returns>操作结果</returns>
|
||||||
[HttpPost("SignUpUser")]
|
[HttpPost("SignUpUser")]
|
||||||
public IResult SignUpUser(string name)
|
public IActionResult SignUpUser(string name, string email, string password)
|
||||||
{
|
{
|
||||||
if (name.Length > 255)
|
if (name.Length > 255)
|
||||||
return TypedResults.BadRequest("Name Couln't over 255 characters");
|
return BadRequest("Name Couln't over 255 characters");
|
||||||
|
|
||||||
using var db = new Database.AppDataConnection();
|
using var db = new Database.AppDataConnection();
|
||||||
var ret = db.AddUser(name);
|
var ret = db.AddUser(name, email, password);
|
||||||
return TypedResults.Ok(ret);
|
return Ok(ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using DotNext;
|
||||||
using LinqToDB;
|
using LinqToDB;
|
||||||
using LinqToDB.Data;
|
using LinqToDB.Data;
|
||||||
using LinqToDB.Mapping;
|
using LinqToDB.Mapping;
|
||||||
|
@ -20,6 +21,46 @@ public class User
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[NotNull]
|
[NotNull]
|
||||||
public required string Name { get; set; }
|
public required string Name { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 用户的电子邮箱
|
||||||
|
/// </summary>
|
||||||
|
[NotNull]
|
||||||
|
public required string EMail { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [TODO:description]
|
||||||
|
/// </summary>
|
||||||
|
[NotNull]
|
||||||
|
public required string Password { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [TODO:description]
|
||||||
|
/// </summary>
|
||||||
|
[NotNull]
|
||||||
|
public required UserPermission Permission { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [TODO:description]
|
||||||
|
/// </summary>
|
||||||
|
[Nullable]
|
||||||
|
public Guid BoardID { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [TODO:description]
|
||||||
|
/// </summary>
|
||||||
|
public enum UserPermission
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// [TODO:description]
|
||||||
|
/// </summary>
|
||||||
|
Admin,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [TODO:description]
|
||||||
|
/// </summary>
|
||||||
|
Normal,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -31,13 +72,47 @@ public class Board
|
||||||
/// FPGA 板子的唯一标识符
|
/// FPGA 板子的唯一标识符
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PrimaryKey]
|
[PrimaryKey]
|
||||||
public Guid Id { get; set; } = Guid.NewGuid();
|
public Guid ID { get; set; } = Guid.NewGuid();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// FPGA 板子的名称
|
/// FPGA 板子的名称
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[NotNull]
|
[NotNull]
|
||||||
public required string BoardName { get; set; }
|
public required string BoardName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [TODO:description]
|
||||||
|
/// </summary>
|
||||||
|
[NotNull]
|
||||||
|
public required string IpAddr { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [TODO:description]
|
||||||
|
/// </summary>
|
||||||
|
[NotNull]
|
||||||
|
public required int Port { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [TODO:description]
|
||||||
|
/// </summary>
|
||||||
|
[NotNull]
|
||||||
|
public required BoardStatus Status { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [TODO:description]
|
||||||
|
/// </summary>
|
||||||
|
public enum BoardStatus
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// [TODO:description]
|
||||||
|
/// </summary>
|
||||||
|
Busy,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [TODO:description]
|
||||||
|
/// </summary>
|
||||||
|
Available,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -45,6 +120,8 @@ public class Board
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AppDataConnection : DataConnection
|
public class AppDataConnection : DataConnection
|
||||||
{
|
{
|
||||||
|
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
static readonly LinqToDB.DataOptions options =
|
static readonly LinqToDB.DataOptions options =
|
||||||
new LinqToDB.DataOptions()
|
new LinqToDB.DataOptions()
|
||||||
.UseSQLite($"Data Source={Environment.CurrentDirectory}/Database.sqlite");
|
.UseSQLite($"Data Source={Environment.CurrentDirectory}/Database.sqlite");
|
||||||
|
@ -77,30 +154,87 @@ public class AppDataConnection : DataConnection
|
||||||
/// 添加一个新的用户到数据库
|
/// 添加一个新的用户到数据库
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="name">用户的名称</param>
|
/// <param name="name">用户的名称</param>
|
||||||
|
/// <param name="email">[TODO:parameter]</param>
|
||||||
|
/// <param name="password">[TODO:parameter]</param>
|
||||||
/// <returns>插入的记录数</returns>
|
/// <returns>插入的记录数</returns>
|
||||||
public int AddUser(string name)
|
public int AddUser(string name, string email, string password)
|
||||||
{
|
{
|
||||||
var user = new User()
|
var user = new User()
|
||||||
{
|
{
|
||||||
Name = name
|
Name = name,
|
||||||
|
EMail = email,
|
||||||
|
Password = password,
|
||||||
|
Permission = Database.User.UserPermission.Normal,
|
||||||
};
|
};
|
||||||
return this.Insert(user);
|
return this.Insert(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [TODO:description]
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">[TODO:parameter]</param>
|
||||||
|
/// <param name="password">[TODO:parameter]</param>
|
||||||
|
/// <returns>[TODO:return]</returns>
|
||||||
|
public Result<Optional<User>> CheckUserPassword(string name, string password)
|
||||||
|
{
|
||||||
|
var user = this.User.Where((user) => user.Name == name).ToArray();
|
||||||
|
|
||||||
|
if (user.Length > 1)
|
||||||
|
{
|
||||||
|
logger.Error($"TODO");
|
||||||
|
return new(new Exception($""));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user[0].Password == password) return new(user[0]);
|
||||||
|
else return new(Optional.Null<User>());
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 添加一块新的 FPGA 板子到数据库
|
/// 添加一块新的 FPGA 板子到数据库
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="name">FPGA 板子的名称</param>
|
/// <param name="name">FPGA 板子的名称</param>
|
||||||
|
/// <param name="ipAddr">[TODO:Param]</param>
|
||||||
|
/// <param name="port">[TODO:Param]</param>
|
||||||
/// <returns>插入的记录数</returns>
|
/// <returns>插入的记录数</returns>
|
||||||
public int AddBoard(string name)
|
public int AddBoard(string name, string ipAddr, int port)
|
||||||
{
|
{
|
||||||
var board = new Board()
|
var board = new Board()
|
||||||
{
|
{
|
||||||
BoardName = name
|
BoardName = name,
|
||||||
|
IpAddr = ipAddr,
|
||||||
|
Port = port,
|
||||||
|
Status = Database.Board.BoardStatus.Available,
|
||||||
};
|
};
|
||||||
return this.Insert(board);
|
return this.Insert(board);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [TODO:description]
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>[TODO:return]</returns>
|
||||||
|
public Optional<Board> GetAvailableBoard()
|
||||||
|
{
|
||||||
|
var boards = this.Board.Where(
|
||||||
|
(board) => board.Status == Database.Board.BoardStatus.Available
|
||||||
|
).ToArray();
|
||||||
|
|
||||||
|
if (boards.Length < 0)
|
||||||
|
{
|
||||||
|
logger.Warn($"TODO");
|
||||||
|
return new(null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var board = boards[0];
|
||||||
|
board.Status = Database.Board.BoardStatus.Busy;
|
||||||
|
this.Board
|
||||||
|
.Where(target => target.ID == board.ID)
|
||||||
|
.Set(target => target.Status, board.Status)
|
||||||
|
.Update();
|
||||||
|
return new(board);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 用户表
|
/// 用户表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1,16 +1,13 @@
|
||||||
<template>
|
<template>
|
||||||
<header></header>
|
<div class="min-h-screen bg-base-100 container mx-auto p-6 space-y-6">
|
||||||
<main class="relative">
|
<ul class="menu bg-base-200 w-56 gap-2 rounded-2xl">
|
||||||
<div class="w-screen h-screen flex items-center justify-center">
|
<li><a>Item 1</a></li>
|
||||||
<UploadCard />
|
<li><a>Item 2</a></li>
|
||||||
</div>
|
<li><a>Item 3</a></li>
|
||||||
</main>
|
</ul>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts"></script>
|
||||||
import UploadCard from "@/components/UploadCard.vue";
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped></style>
|
||||||
@import "../assets/main.css";
|
|
||||||
</style>
|
|
||||||
|
|
Loading…
Reference in New Issue