반응형
어제 트레킹 갓다오고 온몸이 주먹으로 맞은 것 가타요
오늘은요
JWT 로그인 API를 만들엇읍니다
이제 안전한 인증이 가능해짐~!
여기에 회원가입, 프로필 조회, 프로필 수정, 좋아요, 알림 기능을 구현했어요
네 휴일이라 열띰히 했습니닷
그리고 API 작업 너무너무너무 빨리 끝내고 싶음
진심 그만 보고 싶습니다 .... 안 할 수도 없고 이거
🚀 요약
작업 시간: 7시간
✅ 페이지별 필요한 API 구현 (진행중)
🚀 페이지별 필요한 API 구현
JWT 로그인 인증
using Microsoft.AspNetCore.Mvc;
[Route("api/auth")]
[ApiController]
public class AuthController : ControllerBase
{
private readonly AuthService _authService;
public AuthController(AuthService authService)
{
_authService = authService;
}
// ✅ 로그인 API (POST: api/auth/login)
[HttpPost("login")]
public async Task<IActionResult> Login([FromBody] LoginDto loginDto)
{
var token = await _authService.Authenticate(loginDto);
if (token == null)
{
return Unauthorized(new { message = "Invalid email or password" });
}
return Ok(new { token });
}
}
AuthController
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.Extensions.Configuration;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
public class AuthService
{
private readonly AppDbContext _context;
private readonly IConfiguration _configuration;
public AuthService(AppDbContext context, IConfiguration configuration)
{
_context = context;
_configuration = configuration;
}
public async Task<string?> Authenticate(LoginDto loginDto)
{
// 1️⃣ 사용자 정보 확인 (이메일로 검색)
var user = await _context.Users.FirstOrDefaultAsync(u => u.Email == loginDto.Email);
if (user == null) return null; // 사용자 없음
// 2️⃣ 비밀번호 검증 (실제 환경에서는 암호화된 비밀번호를 비교해야 함)
if (user.PasswordHash != loginDto.Password)
{
return null; // 비밀번호 불일치
}
// 3️⃣ JWT 토큰 생성
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.UTF8.GetBytes(_configuration["Jwt:SecretKey"] ?? "defaultSecretKey");
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
new Claim(ClaimTypes.Email, user.Email),
//new Claim("Username", user.Username)
}),
Expires = DateTime.UtcNow.AddHours(2), // 토큰 만료 시간 설정
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token); // JWT 토큰 반환
}
}
LoginService
회원가입, 프로필 조회, 프로필 수정
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
[Route("api/users")]
[ApiController]
public class UserController : ControllerBase
{
private readonly UserService _userService;
public UserController(UserService userService)
{
_userService = userService;
}
// 1️⃣ Register User (POST /api/users/register)
[HttpPost("register")]
public async Task<IActionResult> Register([FromBody] RegisterDto registerDto)
{
var user = await _userService.RegisterUserAsync(registerDto);
if (user == null)
return BadRequest(new { message = "Email is already in use." });
return CreatedAtAction(nameof(GetProfile), new { id = user.Id }, user);
}
// 2️⃣ Get User Profile (GET /api/users/me)
[Authorize]
[HttpGet("me")]
public async Task<IActionResult> GetProfile()
{
var userId = int.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)!);
var user = await _userService.GetUserProfileAsync(userId);
return user != null ? Ok(user) : NotFound();
}
// 3️⃣ Update User Profile (PUT /api/users/me)
[Authorize]
[HttpPut("me")]
public async Task<IActionResult> UpdateProfile([FromBody] UserDto updatedUser)
{
var userId = int.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)!);
var success = await _userService.UpdateUserProfileAsync(userId, updatedUser);
return success ? Ok(new { message = "Profile updated successfully." }) : NotFound();
}
}
UserController
using Microsoft.EntityFrameworkCore;
using System.Security.Cryptography;
using System.Text;
public class UserService
{
private readonly AppDbContext _context;
public UserService(AppDbContext context)
{
_context = context;
}
public async Task<UserDto?> RegisterUserAsync(RegisterDto registerDto)
{
if (await _context.Users.AnyAsync(u => u.Email == registerDto.Email))
return null;
var hashedPassword = HashPassword(registerDto.Password);
var username = registerDto.Email.Split('@')[0];
var newUser = new User
{
Email = registerDto.Email,
Username = username,
PasswordHash = hashedPassword,
CreatedAt = DateTime.UtcNow
};
_context.Users.Add(newUser);
await _context.SaveChangesAsync();
return new UserDto
{
Id = newUser.Id,
Email = newUser.Email,
Username = newUser.Username
};
}
public async Task<UserDto?> GetUserProfileAsync(int userId)
{
var UserItem = await _context.Users.Where(u => u.Id == userId).FirstOrDefaultAsync();
if (UserItem == null) return null;
return new UserDto
{
Id = UserItem.Id,
ProfileImageUrl = UserItem.ProfileImageUrl,
Email = UserItem.Email,
Username = UserItem.Username,
Birthday = UserItem.Birthday
};
}
public async Task<bool> UpdateUserProfileAsync(int userId, UserDto updatedUser)
{
var user = await _context.Users.FindAsync(userId);
if (user == null) return false;
user.Username = !string.IsNullOrWhiteSpace(updatedUser.Username) ? updatedUser.Username : user.Username;
user.ProfileImageUrl = updatedUser.ProfileImageUrl ?? user.ProfileImageUrl;
user.Birthday = updatedUser.Birthday ?? user.Birthday;
user.UpdatedAt = DateTime.UtcNow;
await _context.SaveChangesAsync();
return true;
}
private string HashPassword(string password)
{
using var sha256 = SHA256.Create();
var bytes = Encoding.UTF8.GetBytes(password);
var hash = sha256.ComputeHash(bytes);
return Convert.ToBase64String(hash);
}
}
UserService
왜인지 포스트맨 요청 날리는데 JWT 인증에 계속 실패해서 그거랑 싸우러 감.. 이만
반응형
'study > 100 days (100일 챌린지)' 카테고리의 다른 글
[웹개발 100일] Day 19 - 소소한 UI 디테일 추가 (1) | 2025.03.04 |
---|---|
[웹개발 100일] Day 18 - ASP.NET 백엔드 기초 보안 처리 (XSS 입력값 검증) (5) | 2025.03.03 |
[웹개발 100일] Day 16 - 페이지 별 필요한 API endpoint 구현 (글 작성, 글 목록 검색 및 조회, 글 상세 조회) (0) | 2025.03.01 |
[웹개발 100일] Day 15 - EF Core Include(), Select() 사용해서 테이블 조인해오기 (0) | 2025.02.28 |
[웹개발 100일] Day 14 - ASP.NET API Controller, Service, DTO의 개념과 설계 / Postman으로 테스트 (3) | 2025.02.27 |