์ƒ์„ธ ์ปจํ…์ธ 

๋ณธ๋ฌธ ์ œ๋ชฉ

[Spring] JWT Token ์‚ฌ์šฉํ•˜๊ธฐ

PROGRAMMING/Backend

by koharin 2022. 2. 27. 23:54

๋ณธ๋ฌธ

728x90
๋ฐ˜์‘ํ˜•

๐Ÿ“ JWT ๊ตฌ์กฐ

  • ํ—ค๋”(Header) + ๋‚ด์šฉ(payload) + ์„œ๋ช…(Signature)
  • ํ—ค๋”: typ (ํ† ํฐ ํƒ€์ž…) + alg (ํ•ด์‹ฑ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ •๋ณด ex. RSA, SHA256 ๋“ฑ)
  • ๋‚ด์šฉ(payload) : ํ† ํฐ์— ๋‹ด๋Š” ์ •๋ณด → ํด๋ ˆ์ž„ (registered claim, public claim, private claim)
  • ์„œ๋ช…(signature) : ํ—ค๋”์˜ ์ธ์ฝ”๋”ฉ ๊ฐ’๊ณผ ๋‚ด์šฉ์˜ ์ธ์ฝ”๋”ฉ ๊ฐ’ ํ•ฉ์ณ์„œ ์ฃผ์–ด์ง„ secret key๋กœ ํ•ด์‹ฑํ•˜์—ฌ ์ƒ์„ฑํ•œ ๊ฐ’์œผ๋กœ, ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ์ž์˜ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ secret key๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

 

 

๐Ÿ“ OAuth2 ํ† ํฐ ์ธ์ฆ

  1. ์‚ฌ์šฉ์ž๋Š” ID ํŒจ์Šค์›Œ๋“œ(credential) ์ž…๋ ฅํ•ด์„œ POST๋กœ ์„œ๋ฒ„์— ์š”์ฒญ ๋ณด๋ƒ„
  2. ์„œ๋ฒ„์—์„œ ์‚ฌ์šฉ์ž credential ๊ฒ€์ฆ ํ›„ JWT token ์ƒ์„ฑ
  3. JWT token์„ ์•ˆ๋“œ๋กœ์ด๋“œ ๊ธฐ๊ธฐ์— ์ €์žฅ. ๋ณด์•ˆ์ด ์ ์šฉ๋˜๋Š” ์•ˆ์ „ํ•œ ์žฅ์†Œ์— ๋ณด๊ด€ํ•œ๋‹ค. token์€ API ์š”์ฒญ ์‹œ ์‚ฌ์šฉ
  4. JWT token ๋งŒ๋ฃŒ ์‹œ ๋‹ค์‹œ ID์™€ ํŒจ์Šค์›Œ๋“œ ์ž…๋ ฅํ•˜๋Š”(์‚ฌ์šฉ์ž ์ธ์ฆ) ์•กํ‹ฐ๋น„ํ‹ฐ ๋„์šด๋‹ค.

 

 

๐Ÿ“ Authentication

  • ์‚ฌ์šฉ์ž ์ธ์ฆ
    • token
  • JWT Token ์œ ํšจ์„ฑ ๊ฒ€์ฆ
    • secret key๋กœ JWT ํ† ํฐ ๋””์ฝ”๋”ฉํ•œ๋‹ค. 
    • ํŽ˜์ด๋กœ๋“œ์˜ userId์™€ ์‚ฌ์šฉ์ž๊ฐ€ ์ œ๊ณตํ•œ userId๊ฐ€ ๋™์ผํ•œ์ง€ ๋น„๊ตํ•˜์—ฌ ์ธ์ฆํ•œ๋‹ค.
    • ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ž์› ์ ‘๊ทผ ๊ถŒํ•œ์„ ์ œ๊ณตํ•œ๋‹ค.

 

 

 

๐Ÿ“ JWT ํ† ํฐ์— ํฌํ•จํ•  payload 

  • credential (userId)
    • ๋‹ค๋ฅธ ์ •๋ณด๋„ ํฌํ•จํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ํ† ํฐ์€ ์‚ฌ์šฉ์ž๋ฅผ ์‹๋ณ„ํ•  ์ˆ˜๋งŒ ์žˆ์œผ๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉ์ž ์ •๋ณด์—์„œ _Id (SQL์—์„œ๋Š” primary key)์— ํ•ด๋‹นํ•˜๋Š” userId๋งŒ ์žˆ์–ด๋„ ์‚ฌ์šฉ์ž๋ฅผ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ์–ด์„œ userId๋งŒ ๋„ฃ๊ธฐ๋กœ ํ–ˆ๋‹ค.

 

 

๐Ÿ“ JWT ๋กœ์ง

  • ๋กœ๊ทธ์ธ ์ธ์ฆ
    • credential(id, password) ์ •๋ณด์™€ ํ•จ๊ป˜ ๋กœ๊ทธ์ธ ์ธ์ฆ ์š”์ฒญ์— ๋Œ€ํ•ด ์ธ์ฆ ํ›„, ํ† ํฐ์„ ๋ฐœ๊ธ‰ํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ์— ๋ฆฌํ„ดํ•œ๋‹ค. 
  • ๋กœ๊ทธ์ธ ์œ ์ง€
    • ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ ์œ ์ง€๋ฅผ ์ฒดํฌํ•œ ๊ฒฝ์šฐ ํ† ํฐ ์œ ํšจ๊ธฐ๊ฐ„์„ ๊ธธ๊ฒŒ ์„ค์ • (์œ ํšจ๊ธฐ๊ฐ„์„ ์—†๊ฒŒ ํ•˜์ง€๋Š” ์•Š๊ณ  ์œ ํšจ๊ธฐ๊ฐ„์„ ๊ธธ๊ฒŒ ์„ค์ •ํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค.)
  • ์‚ฌ์šฉ์ž์—๊ฒŒ ํ† ํฐ ๋ฐ˜ํ™˜

 

 

๐Ÿ“ JWT Token์„ ์ด์šฉํ•œ ๋กœ๊ทธ์ธ ์ธ์ฆ ๊ตฌํ˜„

Dependency

<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>
  • pom.xml ํŒŒ์ผ์— ์œ„์˜ maven dependency ์ถ”๊ฐ€

 

JWT ํ† ํฐ ํด๋ž˜์Šค

@Service
public class JWTService {
	private static final String secretKey = "secretkey";
	private long expire = 1000L * 60 * 60 * 24; // ํ† ํฐ ์œ ํšจ๊ธฐ๊ฐ„: 24์‹œ๊ฐ„
	// ํ† ํฐ ์ƒ์„ฑ ๋ฉ”์†Œ๋“œ
	public String createToken(User user, String AutoLogin) {
		// ํ† ํฐ ์„œ๋ช… ์•Œ๊ณ ๋ฆฌ์ฆ˜ 
		SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
		// ๋กœ๊ทธ์ธ ์œ ์ง€ ์ฒดํฌ ์•ˆ ๋œ ๊ฒฝ์šฐ - 7์ผ ์œ ํšจ
		if(AutoLogin.equals("true")) {
			return Jwts.builder()
					.setHeaderParam("typ", "JWT")
					.claim("id", user.getId())
					.setExpiration(new Date(System.currentTimeMillis() + 7*expire))
					.signWith(signatureAlgorithm, secretKey.getBytes())
					.compact();
		}else{ // ๋กœ๊ทธ์ธ ์œ ์ง€ ์ฒดํฌ๋œ ๊ฒฝ์šฐ - expire ์žˆ๊ธด ํ•จ
			return Jwts.builder()
					.setHeaderParam("typ", "JWT") // ํ† ํฐ ํƒ€์ž…
					.claim("id", user.getId()) // payload ๋„ฃ๊ธฐ
					.setExpiration(new Date(System.currentTimeMillis() + expire))
					.signWith(signatureAlgorithm, secretKey.getBytes()) // ํ† ํฐ ์„œ๋ช…
					.compact(); // ์ง๋ ฌํ™”
		}		
	}
	// ํ† ํฐ ์† claim ์ •๋ณด ๊ฐ€์ ธ์˜ค๋Š” ๋ฉ”์†Œ๋“œ
	public Claims getClaim(String token) {
		Claims claims = Jwts.parser()
				.setSigningKey(secretKey.getBytes())
				.parseClaimsJws(token)
				.getBody();
		return claims;
	}

	// JWT token ์œ ํšจ์„ฑ ๊ฒ€์ฆ ๋ฉ”์†Œ๋“œ
	public boolean checkTokenExp(String token) {
		try{
			Claims claims = Jwts.parser()
					.setSigningKey(secretKey.getBytes())
					.parseClaimsJws(token)
					.getBody();
			System.out.println("[+] expire: " + claims.getExpiration());
			return true;
		}catch(ExpiredJwtException e) { // ํ† ํฐ ๋งŒ๋ฃŒ๋œ ๊ฒฝ์šฐ
			System.out.println("[-] Token Expired");
			return false;
		}catch(JwtException e) { // ํ† ํฐ ๋ณ€์กฐ๋œ ๊ฒฝ์šฐ
			System.out.println("[-] Token Modified");
			return false;
		}
	}
}
  • createToken: ํ† ํฐ ์ƒ์„ฑ ๋ฉ”์†Œ๋“œ. ํ† ํฐ ํƒ€์ž…(JWT), claim ์ •๋ณด(id), ํ† ํฐ ์œ ํšจ๊ธฐ๊ฐ„, ํ† ํฐ ์„œ๋ช… ๋ฐฉ๋ฒ•์„ ์ง€์ •ํ•ด์„œ ํ† ํฐ ์ƒ์„ฑํ•˜๋Š” ๋ฉ”์†Œ๋“œ
  • getClaim: ํ† ํฐ์— ๋‹ด๊ธด claim ์ •๋ณด (id)๋ฅผ ํ† ํฐ ์ƒ์„ฑ ์‹œ ์‚ฌ์šฉํ•œ secret key๋กœ ์–ป๋Š” ๋ฉ”์†Œ๋“œ
  • checkTokenExp: ํ† ํฐ ์œ ํšจ์„ฑ ๊ฒ€์ฆํ•˜๋Š” ๋ฉ”์†Œ๋“œ

 

Spring ๋กœ๊ทธ์ธ ์ธ์ฆ ๋ฉ”์†Œ๋“œ

// ๋กœ๊ทธ์ธ
	@PostMapping("signIn/general")
	public User signInAuth(@RequestBody HashMap<String,String> loginInfo, HttpServletResponse response) {
		System.out.println("[+] Login authentication from Android");
		
		System.out.println("[+] id: " + loginInfo.get("id") + ", password: " + loginInfo.get("password") + ", AutoLogin: " + loginInfo.get("AutoLogin"));
		List<User> list = mongoTemplate.find(new Query(new Criteria("_id").is(loginInfo.get("id")).and("password").is(loginInfo.get("password"))), User.class, "User");
		if(list.size() > 0) {
			
			System.out.println("[+] Login Success");
			System.out.println(list.get(0).toString());
			// JWT Token ์ƒ์„ฑ
			String token = jwtService.createToken(list.get(0), loginInfo.get("AutoLogin"));
			System.out.println("token: " + token);
			// HTTP ํ—ค๋”์— token ๋„ข๊ธฐ
			response.setHeader("jwt-token", token); 
		
			return list.get(0);
		}else {
			System.out.println("[+] Login Failed");
			return null; 
		}
	}
  • client์—์„œ (์—ฌ๊ธฐ์„œ๋Š” ์•ˆ๋“œ๋กœ์ด๋“œ) ๋ณด๋‚ธ credential(id, password) ์ •๋ณด๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž๋ฅผ ์ธ์ฆํ•˜๊ณ , createToken ๋ฉ”์†Œ๋“œ๋กœ ํ† ํฐ์„ ๋ฐœ๊ธ‰ํ•ด์ค€๋‹ค. ์ดํ›„ http ํ—ค๋”์— ํ† ํฐ์„ ๋„ฃ๊ณ  ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

 

 

๋กœ๊ทธ์ธ ์ธ์ฆ ๊ฒฐ๊ณผ (Spring)

  • ํด๋ผ์ด์–ธํŠธ(์•ˆ๋“œ๋กœ์ด๋“œ)๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ์ •๋ณด๋กœ๋ถ€ํ„ฐ ์‚ฌ์šฉ์ž ์ธ์ฆ์„ ํ•˜๊ณ  ํ† ํฐ์ด ๋ฐœ๊ธ‰๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๋กœ๊ทธ์ธ ์ธ์ฆ ๊ฒฐ๊ณผ (Android)

  • ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋กœ๊ทธ์ธ ์ธ์ฆ ๊ฒฐ๊ณผ ์‘๋‹ต์„ ๋ฐ›๋Š” ์„ฑ๊ณตํ•ด์„œ ์‚ฌ์šฉ์ž ์ •๋ณด์™€ ํ† ํฐ ์ •๋ณด๋ฅผ ๋ฐ›์€ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

728x90
๋ฐ˜์‘ํ˜•

๊ด€๋ จ๊ธ€ ๋”๋ณด๊ธฐ