abarthdew / spring-boot-jwt-tutorial

๐ŸทJwt tutorial for Spring Boot

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

* Spring Boot JWT Tutorial *

1. JWT ์†Œ๊ฐœ, ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

  • JWT ์žฅ์ : ๊ฐ„ํŽธํ•˜๊ณ  ์‰ฝ๊ฒŒ ์ ์šฉ ๊ฐ€๋Šฅ โ†’ ์‚ฌ์ด๋“œ ํ”„๋กœ์ ํŠธ ์ง„ํ–‰ ์‹œ ์œ ์šฉ

Untitled

Untitled

Untitled

Untitled

Untitled

Untitled

โ‡’ ์ด ๋ฌธ์ž์—ด์„ ํ†ตํ•ด ์„œ๋ฒ„์—์„œ ํ•ด๋‹น ํ† ํฐ์ด ์œ ์šฉํ•œ์ง€ ๊ฒ€์ฆ

Untitled

์‹ค์ „

  • lombok ์„ค์ •(intellij ์‚ฌ์šฉ ์‹œ)

Untitled

  • HelloController.java ์ƒ์„ฑ

2. Security ์„ค์ •, Data ์„ค์ •

  • SecurityConfig.java ์ƒ์„ฑ

Untitled

Untitled

Untitled

Untitled

Untitled

JWT ์„ค์ •

  • application.yml ์„ค์ •
  • entity ํŒจํ‚ค์ง€ ์ƒ์„ฑ

User.java

Untitled

Untitled

Authority.java

  • User entity์™€ ๋™์ผ

data.sql ์ƒ์„ฑ

h2-console์„ ์ด์šฉํ•ด ์—”ํ‹ฐํ‹ฐ ์ƒ์„ฑ ์—ฌ๋ถ€ ํ™•์ธ

  • security ์„ค์ • ์ถ”๊ฐ€

  • ๋ฒ„๊ทธ: #5

  • ์‹คํ–‰: shell์— ์ฟผ๋ฆฌ๋ฌธ ์ถœ๋ ฅ

    Hibernate: 
    
        drop table if exists authority CASCADE
    Hibernate:
    
        drop table if exists user CASCADE
    Hibernate:
    
        drop table if exists user_authority CASCADE
    Hibernate:
    
        create table authority (
           authority_name varchar(50) not null,
            primary key (authority_name)
        )
    Hibernate: 
    
        create table user (
           user_id bigint generated by default as identity,
            activated boolean,
            nickname varchar(50),
            password varchar(100),
            username varchar(50),
            primary key (user_id)
        )
    Hibernate: 
    
        create table user_authority (
           user_id bigint not null,
            authority_name varchar(50) not null,
            primary key (user_id, authority_name)
        )
    Hibernate:
    
        alter table user
           add constraint UK_sb8bbouer5wak8vyiiy4pf2bx unique (username)
    Hibernate:
    
        alter table user_authority
           add constraint FK6ktglpl5mjosa283rvken2py5
           foreign key (authority_name)
           references authority
    Hibernate: 
    
        alter table user_authority
           add constraint FKpqlsjpkybgos9w2svcri7j8xy
           foreign key (user_id)
           references user

์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰ ํ›„ DB ์ ‘์†

3. JWT ์ฝ”๋“œ, Security ์„ค์ • ์ถ”๊ฐ€

To Do

  • JWT ์„ค์ • ์ถ”๊ฐ€
  • JWT ๊ด€๋ จ ์ฝ”๋“œ ๊ฐœ๋ฐœ
  • Security ์„ค์ • ์ถ”๊ฐ€

application.yml์— JWT ์„ค์ • ์ถ”๊ฐ€

build.gradle์— JWT ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ถ”๊ฐ€

JWT ๊ฐœ๋ฐœ - jwt ํŒจํ‚ค์ง€ ์ถ”๊ฐ€

  1. TokenProvider.java

  2. JwtFilter.java

  3. JwtSecurityConfig.java

  4. JwtAuthenticationEntryPoint.java

  5. JwtAccessDeniedHandler.java

์œ„ 5๊ฐœ์˜ ํด๋ž˜์Šค๋ฅผ SecurityConfig.java ์— ์ ์šฉ

4. DTO, Repository, ๋กœ๊ทธ์ธ

Untitled

1) ์™ธ๋ถ€์™€์˜ ํ†ต์‹œ์— ์‚ฌ์šฉํ•  DTO ํด๋ž˜์Šค๊ฐ€ ์žˆ๋Š” ํŒจํ‚ค์ง€ ์ƒ์„ฑ

2) respository ํŒจํ‚ค์ง€ ์ƒ์„ฑ

: User entity์— ๋งคํ•‘๋˜๋Š” repository๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด, UserRepository ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์„ฑ

3) service

: SpringSecurity์—์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๋ถ€๋ถ„ ์ค‘ ํ•˜๋‚˜์ธ UserDetailsService๋ฅผ ์ปค์Šคํ…€ํ•˜๊ฒŒ ๊ตฌํ˜„ํ•œ CustomUserDetailsService ํด๋ž˜์Šค ์ƒ์„ฑ

4) ๋กœ๊ทธ์ธ api ์ถ”๊ฐ€: AuthController

5) postman ํ…Œ์ŠคํŠธ

Untitled

(admin์€ data.sql์˜ insert๋ฌธ์ด ์„œ๋ฒ„๊ฐ€ ์‹œ์ž‘๋  ๋•Œ ์ž๋™์‹คํ–‰๋˜์–ด db์— ์ €์žฅ๋œ ์ƒํƒœ)

โ‡’ ๊ฒฐ๊ณผ: ํ† ํฐ ๋ฆฌํ„ด

Untitled

(+) ์œ ์šฉํ•œ ๊ธฐ๋Šฅ

Untitled

5. ํšŒ์›๊ฐ€์ž…, ๊ถŒํ•œ๊ฒ€์ฆ

Untitled

1) SecurityUtil ํŒจํ‚ค์ง€, ํด๋ž˜์Šค ์ƒ์„ฑ: ๊ฐ„๋‹จํ•œ ์œ ํ‹ธ๋ฆฌํ‹ฐ ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•จ

  • SecurityContext์— getAuthentication()์™€ ๊ฐ™์ด Authentication ๊ฐ์ฒด๊ฐ€ ์ €์žฅ๋˜๋Š” ์‹œ์ :

    Untitled

    // JwtFilter.java์˜ doFilter() ๋ฉ”์„œ๋“œ
    
    // request๊ฐ€ ๋“ค์–ด์˜ค๋Š” ์‹œ์ ์— SecurityContext์— Authentication ๊ฐ์ฒด๊ฐ€ ์ €์žฅ๋จ
    SecurityContextHolder.getContext().setAuthentication(authentication);
    • ์ด๋•Œ ์ €์žฅ๋œ ๊ฐ์ฒด๊ฐ€
    // ์—ฌ๊ธฐ์„œ ๊บผ๋‚ด์ง€๊ฒŒ ๋จ
    
    // SecurityUtil.java์˜ getCurrentUsername() ๋ฉ”์„œ๋“œ
    SecurityContextHolder.getContext().getAuthentication();

2) ํšŒ์›๊ฐ€์ž… ๋กœ์ง ์ƒ์„ฑ: UserService ํด๋ž˜์Šค ์ƒ์„ฑ

(1) data.sql์˜ ๊ถŒํ•œ์€ USER, ADMIN

โ†’ UserService์˜ ROLE_USER ๊ถŒํ•œ๊ณผ์˜ ์ฐจ์ด๋ฅผ ํ†ตํ•ด ํ…Œ์ŠคํŠธ

(2) ์˜ค๋ฒ„๋กœ๋”ฉ๋œ ๋‘ ๊ฐ€์ง€ getMyUserWithAuthorities() ๋ฉ”์„œ๋“œ

โ†’ ํ—ˆ์šฉ ๊ถŒํ•œ์„ ๋‹ค๋ฅด๊ฒŒ ํ•ด์„œ, ๊ถŒํ•œ ๊ฒ€์ฆ ๋ถ€๋ถ„ ํ…Œ์ŠคํŠธ

3) Service ๋‚ด ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  Controller ์ƒ์„ฑ

4) ์„œ๋ฒ„ ์‹œ์ž‘ ํ›„ postman, h2-console๋กœ UserController ํšŒ์›๊ฐ€์ž… ํ…Œ์ŠคํŠธ

(1) ํšŒ์›๊ฐ€์ž… ์ง„ํ–‰

Untitled

Hibernate: 
    select
        user0_.user_id as user_id1_1_0_,
        authority2_.authority_name as authorit1_0_1_,
        user0_.activated as activate2_1_0_,
        user0_.nickname as nickname3_1_0_,
        user0_.password as password4_1_0_,
        user0_.username as username5_1_0_,
        authoritie1_.user_id as user_id1_2_0__,
        authoritie1_.authority_name as authorit2_2_0__
    from
        user user0_
    left outer join
        user_authority authoritie1_
            on user0_.user_id=authoritie1_.user_id
    left outer join
        authority authority2_
            on authoritie1_.authority_name=authority2_.authority_name
    where
        user0_.username=?
Hibernate: 
    insert
    into
        user
        (user_id, activated, nickname, password, username)
    values
        (default, ?, ?, ?, ?)
Hibernate: 
    insert
    into
        user_authority
        (user_id, authority_name)
    values
        (?, ?)

(2) ๊ฐ€์ž…์ •๋ณด h2-console์—์„œ ํ™•์ธ

Untitled

  • test3 ๊ณ„์ •์€ USER ๊ถŒํ•œ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Œ
  • admin ๊ณ„์ •์€ ROLE_ADMIN, ROLE_USER ๊ถŒํ•œ 2๊ฐ€์ง€๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Œ

4-2) ์„œ๋ฒ„ ์‹œ์ž‘ ํ›„ postman, h2-console๋กœ UserController get[My]UserInfo() ํ…Œ์ŠคํŠธ

(1) ADMIN ๊ถŒํ•œ๋งŒ ํ—ˆ์šฉํ–ˆ๋˜ api ํ…Œ์ŠคํŠธ

@GetMapping("/admin/{username}")
@PreAuthorize("hasAnyRole('ADMIN')") // ADMIN ๊ถŒํ•œ๋งŒ ํ˜ธ์ถœ
public ResponseEntity<User> getAdminInfo(@PathVariable String username) {
    return ResponseEntity.ok(userService.getUserWithAuthorities(username));
}
  • โ‡’ ๊ทธ๋ƒฅ ์‹คํ–‰ํ•˜๋ฉด ์—๋Ÿฌ๋‚จ

    Untitled

  • USER, ADMIN ๊ถŒํ•œ ๋ชจ๋‘ ๊ฐ€์ง„ admin ๊ณ„์ •์œผ๋กœ ํ† ํฐ ๋ฐœ๊ธ‰

    Untitled

  • Authorization ํƒญ์— ํ† ํฐ ์ ์žฌ

    // Tests ํƒญ
    
    var jsonData = JSON.parse(responseBody) // responseBody์˜ jsonDate๋ฅผ ํŒŒ์‹ฑ
    pm.globals.set("jwt_tutorial_token", jsonData.token);
    // jsonData.token: token ํ•„๋“œ์— ์žˆ๋Š” ๊ฐ’์„
    // โ€œjwt_tutorial_tokenโ€ ๋ณ€์ˆ˜์— ๋‹ด์Œ

    Untitled

    • โ†“ ์ด๋ ‡๊ฒŒ ํ•ด ๋†“์œผ๋ฉด ๋‹ค๋ฅธ request์—์„œ๋„ ํ•ด๋‹น ๋ณ€์ˆ˜์˜ ๊ฐ’ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

    Untitled

(2) admin ๊ณ„์ • ํ† ํฐ์œผ๋กœ test1 ๊ณ„์ • ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ

  • /api/user/test1 : ("hasAnyRole('USER')") // USER ๊ถŒํ•œ๋งŒ ํ˜ธ์ถœ

  • /api/admin/test1 : ("hasAnyRole('ADMIN')") // ADMIN ๊ถŒํ•œ๋งŒ ํ˜ธ์ถœ

    โ‡’ ๋‘˜ ๋‹ค ๋™์ผํ•œ test1 ๊ณ„์ •์˜ ์ •๋ณด๊ฐ€ ์ถœ๋ ฅ๋จ

Untitled

Untitled

(3) admin ๊ณ„์ • ํ† ํฐ์ด ์•„๋‹Œ test1 ํ† ํฐ์„ ๋ฐœ๊ธ‰๋ฐ›๋Š”๋‹ค๋ฉด?

Untitled

โ‡’ ์ƒˆ๋กœ ๋ฐœ๊ธ‰๋œ ํ† ํฐ์€ โ€œjwt_tutorial_tokenโ€ ์ „์—ญ๋ณ€์ˆ˜์— ๋‹ด๊ฒจ์ง€๊ฒŒ ๋จ

  • ("hasAnyRole('ADMIN')") // ADMIN ๊ถŒํ•œ๋งŒ ํ˜ธ์ถœ โ†’ 403 Forbidden ์˜ค๋ฅ˜ ๋ฐœ์ƒ

    Untitled

    โ‡’ test1 ๊ณ„์ •์œผ๋กœ ๋ฐœ๊ธ‰๋ฐ›์€ ํ† ํฐ์€ ํ•ด๋‹น api๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ถŒํ•œ์ด ์—†์Œ

    โ‡’ 403 Forbidden ์˜ค๋ฅ˜: JwtAccessDeniedHandler๊ฐ€ ์ž‘๋™

  • /api/user/test1: ("hasAnyRole('USER')") // USER ๊ถŒํ•œ๋งŒ ํ˜ธ์ถœ โ†’ ์ •์ƒ ์ž‘๋™

Untitled

  • /api/user: ("hasAnyRole('USER','ADMIN')") // @PreAuthorize๋ฅผ ํ†ตํ•ด USER, ADMIN ๋‘ ๊ฐ€์ง€ ๊ถŒํ•œ ๋ชจ๋‘ ํ—ˆ์šฉ โ†’ ์ •์ƒ ์ž‘๋™

Untitled

์ฐธ๊ณ ์ž๋ฃŒ

About

๐ŸทJwt tutorial for Spring Boot


Languages

Language:Java 100.0%