*** 들어가기 전에 이것저것 살펴보기
* 여러 포트에서 동작하게 할 수 있다.
app.Urls.Add("http://localhost:3000")
app.Urls.Add("http://localhost:4000")
app.Run();
* 환경변수에서 포트번호를 읽어와서 설정할 수도 있다.
var app = WebApplication.Create(args);
var port = Environment.GetEnvironmentVariable("PORT") ?? "3000";
app.MapGet("/", () => "Hello world");
app.Run($"http://localhost:{port}");
* 로그온 어플리케이션 시작에 메시지를 쓸 수 있다.
var app = WebApplication.Create(args);
app.Logger.LogInformation("The app started");
app.MapGet("/", () => {return "Hello world"});
app.Run();
* 서비스 추가는 다음과 같다.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMemoryCache();
builder.Services.AddScoped<ITodoRepository, TodoRepository>();
var app = builder.Build();
* 미들웨어를 추가할 수 있다.
var app = WebApplication.Create(args);
app.UseFileServer();
app.MapGet("/", () => "Hello world");
app.Run();
* 예외페이지를 다음과 같이 설정할 수 있다.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => {
throw new InvalidOperationException("Oops, the '/' route has thrown an exception.");
});
app.Run();
그럼 이런 예외 페이지를 띄우게 된다.
* 페이로드를 받아서 무언가를 처리할때
1. 모델을 선언한다.
2. 해당 모델을 인자에다가 받는다고 넣어놓는다.
app.MapGet("/todos", async (TodoDb db) =>
await db.Todos.ToListAsync());
** 최소 api는 인증, 권한부여, 로깅등의 기능 구현이 상대적으로 쉽다.
성능도 전통적인 MVC 패턴의 api들보다 빠르다.
** HttpPost 메서드의 가장 이상적인 반환값은 200 OK가 아니라 201 Created다.
Results.Created(), TypedResults.Created()는 201 응답코드를 반환한다.
* 라우트 파라미터를 다음과 같이 받아서 사용할 수 있다.
app.MapGet("/todos/{id}", async Task<Results<Ok<Todo>, NotFound>> (int id, TodoDb db) =>
await db.Todos.FindAsync(id)
is Todo todo
? TypedResults.Ok(todo)
: TypedResults.NotFound());
* 파라미터 바인딩
- 쿼리 문자열 바인딩 : URL의 쿼리 문자열을 메서드의 매개변수로 바인딩
- 경로 변수 바인딩 : url 경로의 일부분을 매개변수로 바인딩
- 요청 본문 바인딩 : http 요청 본문의 데이터를 매개변수로 바인딩한다.
***** 방법은 다음과 같다.
* 쿼리 문자열 바인딩
app.MapGet("/search", (string query) => $"검색어 : {query}";
* 경로 변수 바인딩
app.MapGet("/items/{id}", (int id) => "아이템 Id :{id});
- URL 경로의 {id} 부분을 int타입의 id 매개변수로 바인딩한다.
* 요청 본문 바인딩
app.MapPost("/items", (Item item) => {
// Item 객체 처리
});
json데이터를 모델(Item)의 클래스로 인스턴스로 바인딩한다.
*** 최소 api (minimal api)에서 반복되는 url은 그룹으로 묶어서 관리할 수 있다. from dotnet 7 ~ )
- 닷넷 7에서 새롭게 도입된 기능
- 엔드포인트를 그룹화할 수 있도록 MapGroup() 확장 메서드를 제공한다.
// MapGroup() 메서드에 URL 접두사를 지정하고 같은 API들을 묶어주면 된다.
var todos = app.MapGroup("/todos");
// 여기에서
app.MapGet("/todos/{id}", async(TodoDb db) =>
await db.Todos.ToListAsync());
// 위에서 app을 todo로 바꾼다.
todos.MapGet("/{id}", async(TodoDb db) =>
await db.Todos.ToListAsync());
그러면 이제 엔드포인트는 /todos/{id}가 된다.
* 스웨거를 사용하기 위해서 필요한 Nuget 패키지는
- Microsoft.OpenApi 혹은 Microsoft.OpenApi.Models
- Swashbuckle.AspNetCore
*** 최소 api에 인증기능을 추가할 수 있다.
var todos = app.MapGroup("/todos").RequireAuthorization();
- 아까 만들었던 todos에다가 RequireAuthorization을 추가한다.
- 이 경우에 jwt token을 가지고 있지 않으면, api 호출을 할 수 없다.
- 인증되지 않은 상태로 api에 접근을 시도하면 401 에러 메시지가 상태값으로 반환된다.
*** jwt
- json web token
- 웹 표준 rfc7519
- 두 당사자 사이에서 정보를 안전하게 전송하기 위한 방법 제공
- 디지털 서명이 가능하기 때문에, 정보가 검증되고 신뢰할 수 있는지 확인할 수 있고, 송신자가 정말로 클레임한 대로 해당 정보를 보낸 것인지 검증할 수 있다.
- 이 토큰은 자체적으로 필요한 모든 정보를 가지고 있다.
ㄴ 중앙 인증 서버를 통하지 않고도 통신하는 양 당사자 간에 인증과 정보 교환을 진행할 수 있다.
ㄴ 주로 인증 및 정보 교환의 목적으로 사용되고
ㄴ 특히 단일 로그인 SSO에서 많이 사용됨
*** dotnet user-jwts create
- JWT 인증을 사용하기 위해서는 토큰 발행 절차가 필요하다.
- Bearer 토큰을 생성한다.
dotnet user-jwts create --project 프로젝트명
- 그 다음, 진입점에 추가한다.
builder.Services.AddAuthentication().AddJwtBearer(); // 인증
builder.Services.AddAuthorization(); // 권한
- 이후에 서비스를 적용한다.
app.UseAuthorization(); // 권한
- 이후에 적용할 api 엔드포인트 설정 뒤에다가 .RequireAuthorization()을 적용하면
app.MapGet("/", () => "Started..!").RequireAuthorization();
인증된 사용자만 해당 api를 콜할 권한을 가지게 된다.
인증되지 않은 사용자가 api를 콜하면 401 에러메시지를 받는다.
근데, 처음에 Swagger 문서를 생성하면 저기 보이는 Authorize 버튼이 없다.
저 버튼을 통해서 Bearer 토큰을 변경할 수 있다.
*** Swagger 문서에 Authorize 기능 추가하려면
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo
{
Version = "v1",
Title = "TEST API",
Description = "An API to get TestData"
});
//추가
options.InferSecuritySchemes();
options.AddSecurityRequirement(new Microsoft.OpenApi.Models.OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme, Id = "Bearer"
}
},
new string[] { }
}
});
// 추가 끝
});
// 추가
builder.Services.Configure<SwaggerGeneratorOptions>(options =>
{
options.InferSecuritySchemes = true;
});
// 추가 끝
- 저 두 코드를 추가하면 된다.
*** 궁금한 점들이 생겨서!
#1. 만약에 토큰을 중간에 다시 생성하면 이전에 쓰던 토큰들은 어떻게 되나?
- 새로운 토큰을 생성하면 이전에 사용되던 토큰의 유효성에 대한 처리방식은 !여러가지!가 있다.
1. 토큰 만료시간 설정
- JWT 토큰은 만료시간( exp 클레임 )을 가지고 있다.
- 새로운 토큰이 생성되면, 이전 토큰은 일정 시간이 지나면 자동으로 만료되고
- 따라서 클라이언트는 새로운 토큰을 사용하도록 유도된다.
2. 블랙리스트 사용
- 서버에서 이전 토큰을 블랙리스트에 추가하는 방법이 있다.
- 블랙리스트는 일반적으로 데이터베이스나 인메모리 저장소에 저장되며, 각 요청 시 토큰이 블랙리스트에 있는지 확인한다.
- 이 방법은 구현이 복잡하고 성능에 영향을 미칠 수 있다.
3. 토큰의 REFRESH 토큰 사용
- JWT와 함께 REFRESH 토큰을 사용하는 방법도 있다.
- 리프레시 토큰은 주기적으로 새로운 액세스 토큰을 발급받기 위해서 사용되는데, 새로운 액세스 토큰이 발급되면, 이전 액세스 토큰은 더이상 유효하지 않다.
- 서버에서 리프레시 토큰을 검증하고 새로운 액세스 토큰을 발급한다.
4. 토큰의 버전 관리
- 토큰에 버전 정보를 포함시켜, 서버에서 현재 유효한 토큰 버전을 관리한다.
- 새로운 토큰을 생성할 때 버전을 증가시키고, 서버는 현재 유효한 버전의 토큰만을 허용하도록 한다.
* 출처
https://www.dotnetnote.com/docs/aspnetcore/aspnetcore-todo-list-with-minimal-apis/
'Dotnet > .NET , ASP.NET CORE' 카테고리의 다른 글
C#에서의 http 요청/응답/사용 (0) | 2024.11.19 |
---|