๐Ÿ’ Spring/Spring Security

6. JWT๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ํ”„๋กœ์ ํŠธ ์„ธํŒ…

iseunghan 2021. 10. 31. 22:08
๋ฐ˜์‘ํ˜•

์ด ํฌ์ŠคํŠธ๋Š” ๋ฐ์–ด ํ”„๋กœ๊ทธ๋ž˜๋ฐ๋‹˜์˜ ์œ ํŠœ๋ธŒ ๊ฐ•์˜๋ฅผ ๋“ฃ๊ณ  ๋‚˜์„œ ์ •๋ฆฌํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค.

 

dependency ์ถ”๊ฐ€

  • Maven
<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.16.0</version>
</dependency>

 

  • Gradle
// https://mvnrepository.com/artifact/com.auth0/java-jwt
implementation group: 'com.auth0', name: 'java-jwt', version: '3.16.0'

 

 

application.yml ์„ค์ •

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: "jdbc:mysql://localhost:3306/JwtTutorial"
    username: "root"
    password: "1234"

  jpa:
    hibernate:
      ddl-auto: create
    database: mysql
    show-sql: true

jpa, db ์„ค์ • ๋ง๊ณ ๋Š” ๋”ฑํžˆ ํ•ด์ค„๊ฑด ์—†๋‹ค..

 

User ์ƒ์„ฑ

@Data
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class User {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String username;
    private String password;
    @Enumerated(EnumType.STRING)
    private USER_ROLES roles;

}

 

USER_ROLES

public enum USER_ROLES {
    ROLE_ADMIN, ROLE_USER
}

 

SecurityConfig

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private CorsFilter corsFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // Session์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ , Stateless ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค๊ฒ ๋‹ค๋Š” ์˜๋ฏธ
                .and()
                .addFilter(corsFilter)  // Cross-Origin ์ •์ฑ… ์‚ฌ์šฉ X ๋ชจ๋“  ์š”์ฒญ ํ—ˆ์šฉ ** @CrossOrigin๊ณผ์˜ ์ฐจ์ด์  : @CrossOrigin์€ ์ธ์ฆ์ด ์—†์„ ๋•Œ ๋ฌธ์ œ, ๊ทธ๋ž˜์„œ ์ง์ ‘ ์‹œํ๋ฆฌํ‹ฐ ํ•„ํ„ฐ์— ๋“ฑ๋ก!
                    .formLogin().disable()
                    .httpBasic().disable()
                .authorizeRequests()
                    .antMatchers("/api/v1/user/**")
                        .hasAnyRole("USER", "MANAGER", "ADMIN")
                    .antMatchers("/api/v1/manager/**")
                        .hasAnyRole("MANAGER", "ADMIN")
                    .antMatchers("/api/v1/admin/**")
                        .hasRole("ADMIN")
                    .anyRequest().permitAll()
                ;
    }
}
  • csrf().disable() : ๊ณต๊ฒฉ์ž๊ฐ€ ์‚ฌ์šฉ์ž๊ฐ€ ์˜๋„์น˜ ์•Š์€ ์š”์ฒญ(csrf)์„ ์ˆ˜ํ–‰ํ•˜๊ฒŒ ํ•˜๋Š” ๊ฒƒ์„ disableํ•œ๋‹ค.
  • sessionManagement().sessionCreationPolicy(SessionCreatationPolicy.STATLESS) : Session์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ , ์„œ๋ฒ„๋ฅผ Statelessํ•˜๊ฒŒ ๊ตฌ์„ฑํ•˜๊ฒ ๋‹ค๋Š” ์˜๋ฏธ
  • formLogin(), httpBasic() : disable
  • "/api/v1/user/**" ๋กœ ๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  ์š”์ฒญ์€ USER, MANAGE, ADMIN ๊ถŒํ•œ์ด ์žˆ์–ด์•ผ ํ•œ๋‹ค.
  • "/api/v1/manager/**" ๋กœ ๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  ์š”์ฒญ์€ MANAGE, ADMIN ๊ถŒํ•œ์ด ์žˆ์–ด์•ผ ํ•œ๋‹ค.
  • "/api/v1/admin/**" ๋กœ ๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  ์š”์ฒญ์€ ADMIN ๊ถŒํ•œ์ด ์žˆ์–ด์•ผ ํ•œ๋‹ค.
  • ๊ทธ ์™ธ ๋‚˜๋จธ์ง€ ์š”์ฒญ์€ ๋ชจ๋‘ ํ—ˆ์šฉํ•œ๋‹ค.

 

CorsConfig

@Configuration
public class CorsConfig {

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);   // ๋‚ด ์„œ๋ฒ„๊ฐ€ ์‘๋‹ต์„ ํ•  ๋•Œ ์‘๋‹ตํ•ด์ค€ json์„ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ• ์ง€๋ฅผ ์„ค์ •
        config.addAllowedOrigin("*");       // ๋ชจ๋“  ip์— ์‘๋‹ต ํ—ˆ์šฉ
        config.addAllowedHeader("*");       // ๋ชจ๋“  header์— ์‘๋‹ต ํ—ˆ์šฉ
        config.addAllowedMethod("*");       // ๋ชจ๋“  HTTP Method ์š”์ฒญ ํ—ˆ์šฉ

         source.registerCorsConfiguration("/api/**", config);    // /api/** ๋กœ ๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  ์š”์ฒญ๋“ค์€ config๋ฅผ ๋”ฐ๋ฅด๋„๋ก ๋“ฑ๋ก!

        return new CorsFilter(source);
    }
}
  • CORS(Cross-Origin Resource Sharing) : ์‰ฝ๊ฒŒ ๋งํ•ด ๋„๋ฉ”์ธ์ด ๋‹ค๋ฅธ ์„œ๋ฒ„๋กœ ๋ฆฌ์†Œ์Šค ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด CORS ์ •์ฑ…์„ ์œ„๋ฐ˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์—๋Ÿฌ ๋ฐœ์ƒ!
  • ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• ?
    1. CorsConfiguration ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ, ์›ํ•˜๋Š” ์š”์ฒญ์— ๋Œ€ํ•ด์„œ ํ—ˆ์šฉ์„ ํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.
    2. HTTP OPTION์œผ๋กœ ๋จผ์ € ์˜ˆ๋น„ ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ , ์„œ๋ฒ„์—์„œ ์š”์ฒญ์„ ํ—ˆ์šฉํ•œ๋‹ค๋Š” ์‘๋‹ต์„ ๋ฐ›์œผ๋ฉด ๊ทธ๋•Œ GET or POST๋กœ ์›ํ•˜๋Š” ๋ฆฌ์†Œ์Šค ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. (์ƒ๋žต)
๋ฐ˜์‘ํ˜•