13편에서는 로그인 API를 구축하는 것까지 해보았다.

로그인 코드를 수정하고 JWT토큰 처리를 해보자

package com.hyeonjoonpark.board_crud.Controller;

import com.hyeonjoonpark.board_crud.Dto.ResponseDto;
import com.hyeonjoonpark.board_crud.Dto.LoginResponseDto;
import com.hyeonjoonpark.board_crud.Dto.LoginDto;
import com.hyeonjoonpark.board_crud.Dto.SignupDto;
import com.hyeonjoonpark.board_crud.Service.AuthService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/auth")
public class AuthController {
    @Autowired AuthService authService;
    @PostMapping("/signUp")
    public ResponseDto<?> signUp(@RequestBody SignupDto requestBody) {
        ResponseDto<?> result = authService.signUp(requestBody);
        return result;
    }

    @PostMapping("/login")
    public ResponseDto<LoginResponseDto> login(@RequestBody LoginDto requestBody) {
        ResponseDto<LoginResponseDto> result = authService.login(requestBody);
        return result;
    }
}

13편에서 했던 코드이다


위 코드에서 다음과 같이

try {
	boolean existed =  userRepository.existsByUserEmailAndUserPassword(userEmail, userPassword);
	if(!existed) {
	return ResponseDto.setFailed("Login Info is Wrong");
}
} catch (Exception e) {
	return ResponseDto.setFailed("Database Error");
}
UserEntity userEntity = null;
try {
	// 값이 존재하면
	userEntity = userRepository.findById(userEmail).get(); // 사용자 이메일을 가져옴
} catch(Exception e) {
	return ResponseDto.setFailed("Database Error");
}
        
userEntity.setUserPassword("");

Repository에 접근하는 코드들은 모두 try~catch로 감싸주자


토큰에 실제 값을 넣어보자

Bearer 인증방식과 JsonWebToken을 사용할 것이다.

jwt.io

토큰을 사용하기 위해 의존성을 주입해야한다.

build.gradle

implementation group: 'io.jsonwebtoken', name: 'jjwt', version: '0.9.1'

의존성을 추가해주자


프로젝트 폴더 및에 Security라는 패키지를 생성하고 TokenProvider 클래스를 생성한다.

Security/TokenProvider 클래스를 작성해보자

package com.hyeonjoonpark.board_crud.Security;

import org.springframework.stereotype.Service;

@Service
public class TokenProvider {
    private static final String SECURITY_KEY = "jwtsecretkey!@";

    public String createJwt(String userEmail) {

    }
}

여기서 SECURTITY_KEY는 JWT를 판별하는 secret key를 선언한 것이고

createJwt 메서드는 JWT를 생성하는 메서드로써 userEmail을 인자로 받는다


public String createJwt(String userEmail) {
	Date exprTime = Date.from(Instant.now().plus(1, ChronoUnit.HOURS));
    return Jwts.builder()
    			.signWith(SignatureAlgorithm.HS512, SECURITY_KEY)
                .setSubject(userEmail)
                .setIssuedAt(new Date())
                .setExpiration(exprTime)
                .compact();
}

코드해석

Date exprTime = Date.from(Instant.now().plus(1, ChronoUnit.HOURS));

토큰 만료시간을 현재시간의 1시간 후로 설정한다

return Jwts.builder()
        .signWith(SignatureAlgorithm.HS512, SECURITY_KEY)
        .setSubject(userEmail)
        .setIssuedAt(new Date())
        .setExpiration(exprTime)
        .compact();

.signWith(SignatureAlgorithm.HS512, SECURITY_KEY)

HS512알고리즘과 위에서 선언한 SECURITY_KEY를 이용한다


복호화

public String validateJwt(String token) {
    Claims claims = Jwts.parser()
            .setSigningKey(SECURITY_KEY) // token을 SECURITY_KEY를 이용해 파싱
            .parseClaimsJws(token)
            .getBody();

    return claims.getSubject(); // token을 파싱해서 토큰 생성할 때 넣은 userEmail을 가져올 수 있다
}

복호화하는 함수이다.

최종코드

package com.hyeonjoonpark.board_crud.Security;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Date;

@Service
public class TokenProvider {
    private static final String SECURITY_KEY = "jwtsecretkey!@";

    // JWT 생성하는 메서드
    public String createJwt(String userEmail) {
        Date exprTime = Date.from(Instant.now().plus(1, ChronoUnit.HOURS));
        return Jwts.builder() // builder를 이용해서 생성
                .signWith(SignatureAlgorithm.HS512, SECURITY_KEY) // 암호화 알고리즘, 시크릿 키
                .setSubject(userEmail) // JWT의 제목
                .setIssuedAt(new Date()) // 생성날짜
                .setExpiration(exprTime) // 만료날짜
                .compact(); // 생성!
    }

    // JWT 검증 메서드
    public String validateJwt(String token) {
        Claims claims = Jwts.parser()
                .setSigningKey(SECURITY_KEY) // token을 SECURITY_KEY를 이용해 파싱
                .parseClaimsJws(token)
                .getBody();

        return claims.getSubject(); // token을 파싱해서 토큰 생성할 때 넣은 userEmail을 가져올 수 있다
    }
}

우리는 TokenProvider를 서비스로 생성했기 때문에

AuthService 에서 불러올 수 있다.

@Autowired TokenProvider tokenProvider;
String token = tokenProvider.createJwt(userEmail);

전체코드

package com.hyeonjoonpark.board_crud.Service;

import antlr.Token;
import com.hyeonjoonpark.board_crud.Dto.LoginResponseDto;
import com.hyeonjoonpark.board_crud.Dto.ResponseDto;
import com.hyeonjoonpark.board_crud.Dto.LoginDto;
import com.hyeonjoonpark.board_crud.Dto.SignupDto;
import com.hyeonjoonpark.board_crud.Entity.UserEntity;
import com.hyeonjoonpark.board_crud.Repository.UserRepository;
import com.hyeonjoonpark.board_crud.Security.TokenProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class AuthService {
    @Autowired UserRepository userRepository;
    @Autowired TokenProvider tokenProvider;
    public ResponseDto<?> signUp(SignupDto dto) {
        String userEmail = dto.getUserEmail();
        String userPassword = dto.getUserPassword();
        String userPasswordCheck = dto.getUserPasswordCheck();

        // email 중복 확인
        try {
            if(userRepository.existsById(userEmail)) { // userEmail이 존재하는지 확인 -> 존재 시 true 존재하지 않으면 false 반환
                return ResponseDto.setFailed("Existed Email!");
            }
        } catch (Exception e) {
            return ResponseDto.setFailed("Database Error");
        }

        if(!userPassword.equals(userPasswordCheck)) {
            return ResponseDto.setFailed("Password is Wrong!");
        } // userPassword와 userPasswordCheck가 일치하지 않으면

        UserEntity userEntity = new UserEntity(dto); // UserEntity 생성

        try {
            // UserRepository를 이용해서 DB에 Entity 저쟝
            userRepository.save(userEntity);
        } catch (Exception e) {
            ResponseDto.setFailed("Database Error");
        }

        return ResponseDto.setSuccess("SignUp Success!", null);
    }

    public ResponseDto<LoginResponseDto> login(LoginDto dto) {
        String userEmail = dto.getUserEmail();
        String userPassword = dto.getUserPassword();

        try {
            boolean existed =  userRepository.existsByUserEmailAndUserPassword(userEmail, userPassword);
            if(!existed) {
                return ResponseDto.setFailed("Login Info is Wrong");
            }
        } catch (Exception e) {
            return ResponseDto.setFailed("Database Error");
        }

        UserEntity userEntity = null;
        try {
            // 값이 존재하면
            userEntity = userRepository.findById(userEmail).get(); // 사용자 이메일을 가져옴
        } catch(Exception e) {
            return ResponseDto.setFailed("Database Error");
        }

        userEntity.setUserPassword("");

        String token = tokenProvider.createJwt(userEmail);
        int exprTime = 3600000; // 한 시간

        LoginResponseDto loginResponseDto = new LoginResponseDto(token, exprTime, userEntity);
        return ResponseDto.setSuccess("Login Success", loginResponseDto);
    }
}

포스트맨으로 테스트하면 정상적으로 토큰이 생성되는 것을 알 수 있다

profile
Backend Developer

0개의 댓글