본문 바로가기

study/100 days (100일 챌린지)

[웹개발 100일] Day 17 - 페이지 별 필요한 API endpoint 구현 (JWT 인증 로그인, 회원가입, 프로필 조회, 프로필 수정)

반응형

 

 

 

 

 

어제 트레킹 갓다오고 온몸이 주먹으로 맞은 것 가타요

 

오늘은요

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 인증에 계속 실패해서 그거랑 싸우러 감.. 이만

 

 

 

반응형