본문 바로가기
Spring boot 프로젝트 기록/3. 인증 백엔드 통합

스프링 시큐리티 통합 -1

by 으노으뇨 2021. 12. 8.
728x90
반응형
SMALL

구현 내용 (시큐리티 통합 주제로)

1. JWT  인증 로직 구현

2. 패스워드 암호화 로직 구현


1. JWT 생성 및 반환 구현

사용자 정보를 바탕으로 헤더와 페이로드를 작성하고 전자 서명한 후 토큰을 리턴하도록 해야합니당

구현을 위해 JWT 관련 라이브러리를 디펜던시에 추가해야해요!

build.gradle의 dependencies 부분에 jjwt 라이브러를 추가해줍시닷!

	// https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt
	implementation group: 'io.jsonwebtoken', name: 'jjwt', version: '0.9.1'

이제 보안을 제대로 구현하기위해 security 패키지를 만듭시다!!

이 패키즈는 인증과 인가를 위한 모든 클래스를 관리하게 해줍시다!!

그리고 security 패키지니 안에 TokenProvider 클래스를 만들어 주어야 합니다.

이 클래스가 하는일은 사용자 정보를 받아 JWT를 생성하는 일입니다!

package com.unoSpringBoot.study.security;

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

import org.springframework.stereotype.Service;

import com.unoSpringBoot.study.model.UserEntity;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class TokenProvider {
	private static final String SECRET_KEY = "NMA8JPcFuna59f5";

	public String create(UserEntity userEntity) {
		Date expirDate = Date.from(Instant.now().plus(1, ChronoUnit.DAYS));
		/*
		 * {//header "alg" : "HS512" }. 
		 * { //payload 
		 * 		"sub" : "40288093784915d201784916a40c001"
		 * , 	"iss" : "demo app"
		 * , 	"iat" : 1595733657
		 * ,	"exp" : 1596597657
		 *  }.
		 */
		//JWT 토큰 생성
		return Jwts.builder()
				//header에 들어갈 내용 및 서명을 하기 위한 secret_key
				.signWith(SignatureAlgorithm.HS512, SECRET_KEY)
				//payload에 들어갈 내용
				.setSubject(userEntity.getId())
				.setIssuer("demo app").setIssuedAt(new Date()).setExpiration(expirDate).compact();
	}

	public String validateAndGetUserId(String token) {
		// parseClaimsJwt 매서드가 Base64로 디코딩 및 파싱
		// 해더와 페이로드를 setSigninKey 로 넘어온 시크릿을 이용해 서명한 후 token의 서명과 비교
		// 위조 되지 않았다면 페이로드(Claims)리턴, 위조라면 예외를 날림
		// 그중 우리는 userId가 필요하므로 getBody를 부른다.
		Claims claims = Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();
		return claims.getSubject();
	}
}

이렇게 작성해 주었다.

보기보다 간단하다. 첫번째 메서드 create는 JWT 라이브러리를 이용해 JWT 토큰을 생성한다.

두번째 메서드는 validateAndGetUserId()토큰을 디코딩 및 파싱하고 토큰의 위조 여부를 확인한다. 

이후 우리가 원하는 subject, 즉 사용자의 아이디를 리턴한다. 

라이브러리 덕에 우리가 굳이 Json을 생성, 서명, 인코딩, 디코딩, 파싱 하는 작업을 하지않아도 됩니다!!

위 코드를 참고해서 TokenProvider를 작성했다면

이제 로그인 부분에서 TokenProvider를 이용해 토큰을 생성한 후 UserDTO에 이를 반환해야합니다!!

어렵다... 천천히 코드를 짜고 설명드리겠습니다.

우선 기존의 SO 서비스단의 /signin <- 로그인하는 URI

를 수정해주어야합니다.

여긴 문제가 없으니 이제 컨트롤 오브젝트로 들어갑니다.

package com.unoSpringBoot.study.Controller.User;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import com.unoSpringBoot.study.DTO.ResponseDTO;
import com.unoSpringBoot.study.DTO.UserDTO;
import com.unoSpringBoot.study.model.UserEntity;
import com.unoSpringBoot.study.security.TokenProvider;
import com.unoSpringBoot.study.service.UserService;

@Service
public class LoginUserCO {
	@Autowired
	private TokenProvider tokenProvide;
	@Autowired
	private UserService service;

	public ResponseEntity<?> authenticate(UserDTO userDTO) {
		UserEntity user = service.getByCredentials(userDTO.getEmail(), userDTO.getPassword());
		if (user != null) {
			// 여기서 부터 토큰생성을 해주는 기능을 넣어준다!
			final String token = tokenProvide.create(user);
			final UserDTO responseUserDTO = UserDTO.builder()
					.email(user.getUsername()).id(user.getId()).token(token).build();
			return ResponseEntity.ok().body(responseUserDTO);
		} else {
			ResponseDTO<?> responseDTO = ResponseDTO.builder().error("로그인 실패 ㅠ").build();
			return ResponseEntity.badRequest().body(responseDTO);
		}
	}
}

수정된 부분은 크게없고 토큰을 만들어주는 토큰프로바리드와 해당 메서드, 그리고 그 토큰을 저장시켜주는

.toke(token)을 builder()뒤에 줄줄이 달아줍시다!

작성을 완료했으면 테스트를통해서 확인해줍시다!!

토큰을 테스트하려면 

애플리케션을 실행시키고 포스트맨에서 localhost:8080/auth.signup에 HTTP POST 매서드 요청을 보내 

계정을 우선 생성해 주어야합니다!!

-아직 DB구축이 ㅠ

raw 에 제이슨형태로 지정해주는것 꼭 잊지맙시다~~

{
    "email" : "zhfldk014745@naver.com",
    "username" : "unokim",
    "password" : "1234"
}

결과를 얻었다 . 지금 회원가입이 성공했다는 것이다. 이제 로그인을 해봅시다!!

localhost:8080/auth/signin 으로 고곸!!

{
"token" : "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI0MDI4ODA4YjdkOWE1MTA3MDE3ZDlhNTUzODEyMDAwMyIsImlzcyI6ImRlbW8gYXBwIiwiaWF0IjoxNjM4OTcyMDEwLCJleHAiOjE2MzkwNTg0MTB9.2vJaGtHuW_yVmLCTowBgj0herZ7tYnpXxtN5uuFdXGlzE5a6_hZlQTDIGr5xy1BFZ3N-Z_GOkrUFOIwRP4hO5g"
, "email": "unokim"
, "username": null
, "password": null
, "id": "4028808b7d9a5107017d9a5538120003"
, "auth": null
}

 

728x90
반응형
LIST

댓글