加入專案檔案。
This commit is contained in:
parent
0422cc08f3
commit
84c75c7d71
12
API註解操作說明(必看).txt
Normal file
12
API註解操作說明(必看).txt
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
JWTdemo資料夾→JWTdemo.csproj 開啟
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings> //新增這兩行
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile> //新增這兩行
|
||||||
|
<NoWarn>$(NoWarn);1591</NoWarn>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
1.<GenerateDocumentationFile>true</GenerateDocumentationFile>:這個設定告訴編譯器生成 XML 註解檔案。當您的專案編譯時,它會將 XML 註解嵌入到組件中,以供 Swagger 或其他工具使用。
|
||||||
|
2.<NoWarn>$(NoWarn);1591</NoWarn>:這個設定用來抑制編譯器警告 1591。警告 1591 是指程式碼中的缺少 XML 註解的警告。這裡的設定的意思是告訴編譯器忽略這個特定的警告,因為您已經啟用了 XML 註解生成,而不希望因缺少註解而收到警告。
|
25
JWTdemo.sln
Normal file
25
JWTdemo.sln
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.7.34031.279
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JWTdemo", "JWTdemo\JWTdemo.csproj", "{4C54D743-8EE0-44C9-8C9D-010A306C4AE7}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{4C54D743-8EE0-44C9-8C9D-010A306C4AE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{4C54D743-8EE0-44C9-8C9D-010A306C4AE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{4C54D743-8EE0-44C9-8C9D-010A306C4AE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{4C54D743-8EE0-44C9-8C9D-010A306C4AE7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {5537568D-28F4-41EA-A9EE-89BAF86E4808}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
6
JWTdemo/Authorization/AllowAnonymousAttribute.cs
Normal file
6
JWTdemo/Authorization/AllowAnonymousAttribute.cs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
namespace JWTdemo.Authorization;
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Method)]
|
||||||
|
public class AllowAnonymousAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
24
JWTdemo/Authorization/AuthorizeAttribute.cs
Normal file
24
JWTdemo/Authorization/AuthorizeAttribute.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using JWTdemo.Entities;
|
||||||
|
|
||||||
|
namespace JWTdemo.Authorization;
|
||||||
|
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
||||||
|
public class AuthorizeAttribute : Attribute, IAuthorizationFilter
|
||||||
|
{
|
||||||
|
public void OnAuthorization(AuthorizationFilterContext context)
|
||||||
|
{
|
||||||
|
// skip authorization if action is decorated with [AllowAnonymous] attribute
|
||||||
|
var allowAnonymous = context.ActionDescriptor.EndpointMetadata.OfType<AllowAnonymousAttribute>().Any();
|
||||||
|
if (allowAnonymous)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// authorization
|
||||||
|
var user = (User?)context.HttpContext.Items["User"];
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
// not logged in or role not authorized
|
||||||
|
context.Result = new JsonResult(new { message = "Unauthorized" }) { StatusCode = StatusCodes.Status401Unauthorized };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
JWTdemo/Authorization/JwtMiddleware.cs
Normal file
23
JWTdemo/Authorization/JwtMiddleware.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
namespace JWTdemo.Authorization;
|
||||||
|
public class JwtMiddleware
|
||||||
|
{
|
||||||
|
private readonly RequestDelegate _next;
|
||||||
|
|
||||||
|
public JwtMiddleware(RequestDelegate next)
|
||||||
|
{
|
||||||
|
_next = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Invoke(HttpContext context, IUserService userService, IJwtUtils jwtUtils)
|
||||||
|
{
|
||||||
|
var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
|
||||||
|
var userId = jwtUtils.ValidateJwtToken(token);
|
||||||
|
if (userId != null)
|
||||||
|
{
|
||||||
|
// attach user to context on successful jwt validation
|
||||||
|
context.Items["User"] = userService.GetById(userId.Value);
|
||||||
|
}
|
||||||
|
//var stop = "1";
|
||||||
|
await _next(context);
|
||||||
|
}
|
||||||
|
}
|
106
JWTdemo/Authorization/JwtUtils.cs
Normal file
106
JWTdemo/Authorization/JwtUtils.cs
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
namespace JWTdemo.Authorization;
|
||||||
|
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Text;
|
||||||
|
using JWTdemo.Entities;
|
||||||
|
using JWTdemo.Helpers;
|
||||||
|
|
||||||
|
|
||||||
|
public interface IJwtUtils
|
||||||
|
{
|
||||||
|
public string GenerateJwtToken(User user);
|
||||||
|
public int? ValidateJwtToken(string? token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class JwtUtils : IJwtUtils
|
||||||
|
{
|
||||||
|
private readonly AppSettings _appSettings;
|
||||||
|
|
||||||
|
public JwtUtils(IOptions<AppSettings> appSettings)
|
||||||
|
{
|
||||||
|
_appSettings = appSettings.Value;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(_appSettings.Secret))
|
||||||
|
throw new Exception("JWT secret not configured");
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GenerateJwtToken(User user)
|
||||||
|
{
|
||||||
|
// generate token that is valid for 7 days
|
||||||
|
var tokenHandler = new JwtSecurityTokenHandler(); //實例化JWT令牌
|
||||||
|
var key = Encoding.ASCII.GetBytes(_appSettings.Secret!); //從配置中獲取應用程序密鑰,用於簽名令牌以確保其完整性和安全性
|
||||||
|
var tokenDescriptor = new SecurityTokenDescriptor //定義令牌格式,其包含header(SigningCredentials).payload(expires和subject).signature(簽在header裡面)
|
||||||
|
{
|
||||||
|
Subject = new ClaimsIdentity(new[] { new Claim("id", user.Id.ToString()) }), //payload
|
||||||
|
Expires = DateTime.UtcNow.AddDays(7), //payload,令牌過期時間
|
||||||
|
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) //header
|
||||||
|
};
|
||||||
|
var token = tokenHandler.CreateToken(tokenDescriptor); //創建JWT令牌
|
||||||
|
return tokenHandler.WriteToken(token); //將JWT令牌轉為base64編碼
|
||||||
|
}
|
||||||
|
|
||||||
|
public int? ValidateJwtToken(string? token)
|
||||||
|
{
|
||||||
|
if (token == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var tokenHandler = new JwtSecurityTokenHandler();
|
||||||
|
var key = Encoding.ASCII.GetBytes(_appSettings.Secret!);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
tokenHandler.ValidateToken(token, new TokenValidationParameters
|
||||||
|
{
|
||||||
|
ValidateIssuerSigningKey = true,
|
||||||
|
IssuerSigningKey = new SymmetricSecurityKey(key),
|
||||||
|
ValidateIssuer = false,
|
||||||
|
ValidateAudience = false,
|
||||||
|
// set clockskew to zero so tokens expire exactly at token expiration time (instead of 5 minutes later)
|
||||||
|
ClockSkew = TimeSpan.Zero
|
||||||
|
}, out SecurityToken validatedToken);
|
||||||
|
|
||||||
|
var jwtToken = (JwtSecurityToken)validatedToken;
|
||||||
|
var userId = int.Parse(jwtToken.Claims.First(x => x.Type == "id").Value);
|
||||||
|
|
||||||
|
// return user id from JWT token if validation successful
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// return null if validation fails
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//0523
|
||||||
|
public bool ValidateToken(string token)
|
||||||
|
{
|
||||||
|
var tokenHandler = new JwtSecurityTokenHandler();
|
||||||
|
var jwtSecret = "your_jwt_secret"; // JWT 密钥,应与生成令牌时使用的密钥相匹配
|
||||||
|
|
||||||
|
var validationParameters = new TokenValidationParameters
|
||||||
|
{
|
||||||
|
ValidateIssuerSigningKey = true,
|
||||||
|
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSecret)),
|
||||||
|
ValidateIssuer = false,
|
||||||
|
ValidateAudience = false,
|
||||||
|
ValidateLifetime = true,
|
||||||
|
ClockSkew = TimeSpan.Zero // 设置为零以确保令牌过期时立即失效
|
||||||
|
};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SecurityToken validatedToken;
|
||||||
|
tokenHandler.ValidateToken(token, validationParameters, out validatedToken);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
28
JWTdemo/Controllers/UserController.cs
Normal file
28
JWTdemo/Controllers/UserController.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using JWTdemo.Services;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using JWTdemo.Models;
|
||||||
|
using JWTdemo.Authorization;
|
||||||
|
|
||||||
|
namespace JWTdemo.Controllers
|
||||||
|
{
|
||||||
|
[Authorize] //有token才能使用class
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
[ApiController]
|
||||||
|
public class UserController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly SqlContext _context;
|
||||||
|
public UserController(SqlContext context)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 測試註解
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<ActionResult<IEnumerable<JWTdemo.Entities.User>>> Getuser()
|
||||||
|
{
|
||||||
|
return await _context.chatuser.ToListAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
14
JWTdemo/Entities/User.cs
Normal file
14
JWTdemo/Entities/User.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace JWTdemo.Entities
|
||||||
|
{
|
||||||
|
public class User
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string? Name { get; set; }
|
||||||
|
public string? Username { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore] //這個就是當有人要get這個資料時,會自動將其隱藏
|
||||||
|
public string? Password { get; set; }
|
||||||
|
}
|
||||||
|
}
|
7
JWTdemo/Helpers/AppSettings.cs
Normal file
7
JWTdemo/Helpers/AppSettings.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace JWTdemo.Helpers
|
||||||
|
{
|
||||||
|
public class AppSettings
|
||||||
|
{
|
||||||
|
public string? Secret { get; set; }
|
||||||
|
}
|
||||||
|
}
|
20
JWTdemo/JWTdemo.csproj
Normal file
20
JWTdemo/JWTdemo.csproj
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<NoWarn>$(NoWarn);1591</NoWarn>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.7" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="6.0.7" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.11" />
|
||||||
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.11" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||||
|
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.30.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
13
JWTdemo/Models/AuthenticateRequest.cs
Normal file
13
JWTdemo/Models/AuthenticateRequest.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
namespace JWTdemo.Models;
|
||||||
|
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
|
||||||
|
public class AuthenticateRequest
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string? Username { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string? Password { get; set; }
|
||||||
|
}
|
20
JWTdemo/Models/AuthenticateResponse.cs
Normal file
20
JWTdemo/Models/AuthenticateResponse.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
namespace JWTdemo.Models;
|
||||||
|
|
||||||
|
using JWTdemo.Entities;
|
||||||
|
|
||||||
|
public class AuthenticateResponse
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string? Name { get; set; }
|
||||||
|
public string? Username { get; set; }
|
||||||
|
public string Token { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public AuthenticateResponse(User user, string token)
|
||||||
|
{
|
||||||
|
Id = user.Id;
|
||||||
|
Name = user.Name;
|
||||||
|
Username = user.Username;
|
||||||
|
Token = token;
|
||||||
|
}
|
||||||
|
}
|
130
JWTdemo/Program.cs
Normal file
130
JWTdemo/Program.cs
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using JWTdemo.Authorization;
|
||||||
|
using JWTdemo.Helpers;
|
||||||
|
using System.Configuration;
|
||||||
|
using System.Reflection;
|
||||||
|
using JWTdemo.Services;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
|
||||||
|
|
||||||
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
builder.Services.AddCors();
|
||||||
|
builder.Services.AddControllers();
|
||||||
|
|
||||||
|
// Add services to the container.
|
||||||
|
//builder.Services.AddControllersWithViews();
|
||||||
|
|
||||||
|
//*------------------------------連線PostgreSQL資料庫-----------------------------------------------
|
||||||
|
var connectionString = "Server=localhost;UserID=postgres;Password=vip125125;Database=postgres;port=5432;";
|
||||||
|
builder.Services.AddDbContext<SqlContext>(opt => opt.UseNpgsql(connectionString));
|
||||||
|
|
||||||
|
//*---------------------------------JWT身分驗證-------------------------------------------------------
|
||||||
|
{
|
||||||
|
var services = builder.Services;
|
||||||
|
services.AddCors();
|
||||||
|
services.AddControllers();
|
||||||
|
services.Configure<AppSettings>(builder.Configuration.GetSection("AppSettings"));
|
||||||
|
var jwtSettings = builder.Configuration.GetSection("AppSettings").Get<AppSettings>();
|
||||||
|
|
||||||
|
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||||
|
.AddJwtBearer(options =>
|
||||||
|
{
|
||||||
|
options.TokenValidationParameters = new TokenValidationParameters
|
||||||
|
{
|
||||||
|
ValidateIssuer = false,
|
||||||
|
ValidateAudience = false,
|
||||||
|
ValidateIssuerSigningKey = true,
|
||||||
|
//ValidIssuer = "your_issuer",
|
||||||
|
// ValidAudience = "your_audience",
|
||||||
|
ClockSkew = TimeSpan.Zero,
|
||||||
|
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.Secret))
|
||||||
|
};
|
||||||
|
});
|
||||||
|
services.AddSwaggerGen(c =>
|
||||||
|
{
|
||||||
|
c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApi_data_value", Version = "v1" });
|
||||||
|
|
||||||
|
// Configure Swagger to use JWT authentication
|
||||||
|
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
|
||||||
|
{
|
||||||
|
Description = "JWT Authorization header using the Bearer scheme",
|
||||||
|
Name = "Authorization",
|
||||||
|
In = ParameterLocation.Header,
|
||||||
|
Type = SecuritySchemeType.ApiKey,
|
||||||
|
Scheme = "Bearer"
|
||||||
|
});
|
||||||
|
|
||||||
|
// 将JWT令牌作为所有端点的要求添加到Swagger文档
|
||||||
|
c.AddSecurityRequirement(new OpenApiSecurityRequirement
|
||||||
|
{
|
||||||
|
{
|
||||||
|
new OpenApiSecurityScheme
|
||||||
|
{
|
||||||
|
Reference = new OpenApiReference
|
||||||
|
{
|
||||||
|
Type = ReferenceType.SecurityScheme,
|
||||||
|
Id = "Bearer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new string[] { }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// configure DI for application services
|
||||||
|
services.AddScoped<IJwtUtils, JwtUtils>();
|
||||||
|
services.AddScoped<IUserService, UserService>();
|
||||||
|
// 注册 HttpClient 服务
|
||||||
|
services.AddHttpClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//*---------------------------創專案就有--------------------------
|
||||||
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
|
builder.Services.AddSwaggerGen();
|
||||||
|
|
||||||
|
//*---------------------------WebAPI註解設定--------------------------
|
||||||
|
builder.Services.AddSwaggerGen(options =>
|
||||||
|
{
|
||||||
|
var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
|
||||||
|
options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
|
||||||
|
});
|
||||||
|
var app = builder.Build();
|
||||||
|
//*---------------------------JWT身分驗證------------------------------
|
||||||
|
{
|
||||||
|
// global cors policy
|
||||||
|
//在 ASP.NET Core 中啟用 CORS (跨原始來源要求)
|
||||||
|
// Shows UseCors with CorsPolicyBuilder.
|
||||||
|
app.UseCors(x => x
|
||||||
|
.AllowAnyOrigin()
|
||||||
|
.AllowAnyMethod()
|
||||||
|
.AllowAnyHeader());
|
||||||
|
|
||||||
|
// custom jwt auth middleware
|
||||||
|
app.UseMiddleware<JwtMiddleware>();
|
||||||
|
|
||||||
|
app.MapControllers();
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------Swagger初始化-------------------------------------
|
||||||
|
if (app.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
app.UseSwagger();
|
||||||
|
app.UseSwaggerUI(c =>
|
||||||
|
{
|
||||||
|
c.SwaggerEndpoint("/swagger/v1/swagger.json", "JWTdemo"); //API註解開啟
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
app.UseHttpsRedirection();
|
||||||
|
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
app.MapControllers();
|
||||||
|
|
||||||
|
app.Run();
|
31
JWTdemo/Properties/launchSettings.json
Normal file
31
JWTdemo/Properties/launchSettings.json
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||||
|
"iisSettings": {
|
||||||
|
"windowsAuthentication": false,
|
||||||
|
"anonymousAuthentication": true,
|
||||||
|
"iisExpress": {
|
||||||
|
"applicationUrl": "http://localhost:23800",
|
||||||
|
"sslPort": 44344
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"profiles": {
|
||||||
|
"JWTdemo": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"applicationUrl": "https://localhost:7079;http://localhost:5246",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IIS Express": {
|
||||||
|
"commandName": "IISExpress",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
25
JWTdemo/Services/SqlContext.cs
Normal file
25
JWTdemo/Services/SqlContext.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using JWTdemo.Entities;
|
||||||
|
|
||||||
|
|
||||||
|
namespace JWTdemo.Services
|
||||||
|
{
|
||||||
|
public class SqlContext : DbContext
|
||||||
|
{
|
||||||
|
public SqlContext(DbContextOptions<SqlContext> options) : base(options)
|
||||||
|
{
|
||||||
|
//連接PostgreSQL
|
||||||
|
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
|
||||||
|
AppContext.SetSwitch("Npgsql.DisableDateTimeInfinityConversions", true);
|
||||||
|
}
|
||||||
|
public DbSet<User>chatuser { get; set; } = null!;
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder builder)
|
||||||
|
{
|
||||||
|
base.OnModelCreating(builder);
|
||||||
|
|
||||||
|
builder.Entity<User>().HasKey(o => new { o.Id }); //Primary Key
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
70
JWTdemo/Services/UserService.cs
Normal file
70
JWTdemo/Services/UserService.cs
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
using JWTdemo.Authorization;
|
||||||
|
using JWTdemo.Services;
|
||||||
|
using JWTdemo.Entities;
|
||||||
|
using JWTdemo.Models;
|
||||||
|
|
||||||
|
public interface IUserService
|
||||||
|
{
|
||||||
|
AuthenticateResponse? Authenticate(AuthenticateRequest model);
|
||||||
|
IEnumerable<User> GetAll();
|
||||||
|
User? GetById(int id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UserService : IUserService
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
// users hardcoded for simplicity, store in a db with hashed passwords in production applications
|
||||||
|
private List<User> user_test = new List<User>
|
||||||
|
{
|
||||||
|
new User { Id = 1, FirstName = "Test", LastName = "User", Username = "test", Password = "test" },
|
||||||
|
new User { Id = 2, FirstName = "Test", LastName = "User", Username = "admin", Password = "admin" }
|
||||||
|
};
|
||||||
|
|
||||||
|
public DbSet<User> user_test { get; set; } = null!;
|
||||||
|
|
||||||
|
|
||||||
|
public List<User> GetUsers ()
|
||||||
|
{
|
||||||
|
return _dbContext.user_test.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
private readonly IJwtUtils _jwtUtils;
|
||||||
|
|
||||||
|
public UserService(IJwtUtils jwtUtils, SqlContext dbContext)
|
||||||
|
{
|
||||||
|
_jwtUtils = jwtUtils;
|
||||||
|
_dbContext = dbContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private readonly SqlContext _dbContext;
|
||||||
|
|
||||||
|
|
||||||
|
public AuthenticateResponse? Authenticate(AuthenticateRequest model)
|
||||||
|
{
|
||||||
|
var user = _dbContext.chatuser.SingleOrDefault(x => x.Username == model.Username && x.Password == model.Password);
|
||||||
|
|
||||||
|
// return null if user not found
|
||||||
|
if (user == null) return null;
|
||||||
|
|
||||||
|
// authentication successful so generate jwt token
|
||||||
|
var token = _jwtUtils.GenerateJwtToken(user);
|
||||||
|
|
||||||
|
return new AuthenticateResponse(user, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<User> GetAll()
|
||||||
|
{
|
||||||
|
return _dbContext.chatuser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User? GetById(int id)
|
||||||
|
{
|
||||||
|
return _dbContext.chatuser.FirstOrDefault(x => x.Id == id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
8
JWTdemo/appsettings.Development.json
Normal file
8
JWTdemo/appsettings.Development.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
JWTdemo/appsettings.json
Normal file
12
JWTdemo/appsettings.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"AppSettings": {
|
||||||
|
"Secret": "Leo token test jwt park spaces lab 124"
|
||||||
|
},
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*"
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user