BootCamp 56day

GyeongNamΒ·2024λ…„ 2μ›” 6일
0

BootCamp

λͺ©λ‘ 보기
49/49
post-thumbnail

πŸ“… 2024λ…„ 02μ›” 01일

55μΌμ°¨λŠ” μ§€κΈˆκΉŒμ§€ λ°°μš΄κ²ƒμ„ λ³΅μŠ΅ν•œ λ‚΄μš©μ΄λ―€λ‘œ λ”°λ‘œ μ •λ¦¬ν•˜μ§€ μ•Šκ² μŠ΅λ‹ˆλ‹€.


56일차 : Spring (16)

JWT

  • JWTprovider
@Component
public class JWTprovider {
    public String createToken(String email, String role){
        /*
        claims : ν΄λ ˆμž„μ€ 토큰 μ‚¬μš©μžμ˜ λŒ€ν•œ μ†μ„±μ΄λ‚˜ 데이터 포함, 주둜 νŽ˜μ΄λ‘œλ“œλ₯Ό 의미
         */
        Claims claims = Jwts.claims().setSubject(email);
        claims.put("role",role);
        Date now = new Date();
        Key key = Keys.hmacShaKeyFor("μ—¬κΈ°κ°€μ‹œν¬λ¦Ών‚€μΈλ°μ’€κΈΈκ²Œμ„€μ •ν•΄μ•Όν•΄".getBytes(StandardCharsets.UTF_8));
        return Jwts.builder()
                .setClaims(claims) // 정보 μ €μž₯
                .setIssuedAt(now)
                .setExpiration(new Date(now.getTime() + 30 * 60 * 1000L))
                .signWith( key, SignatureAlgorithm.HS256)
                .compact();
    }
}
  • JwtAuthFilter
@Component
public class JwtAuthFilter extends GenericFilter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        try {
            String bearerToken = ((HttpServletRequest) servletRequest).getHeader("Authorization");
            if(bearerToken != null){
                if(!bearerToken.startsWith("Bearer ")){
                    throw new AuthenticationServiceException("토큰 ν˜•μ‹μ΄ λ§žμ§€ μ•ŠμŠ΅λ‹ˆλ‹€.");
                }
                Key key = Keys.hmacShaKeyFor("μ—¬κΈ°κ°€μ‹œν¬λ¦Ών‚€μΈλ°μ’€κΈΈκ²Œμ„€μ •ν•΄μ•Όν•΄".getBytes(StandardCharsets.UTF_8));
                String token = bearerToken.substring(7);
                // 검증 및 ν΄λž˜μž„μŠ€ μΆ”μΆœ
                Claims claims = Jwts.parserBuilder()
                        .setSigningKey(key)
                        .build()
                        .parseClaimsJws(token)
                        .getBody();
                // Authentication 객체λ₯Ό μƒμ„±ν•œκΈ° μœ„ν•œ UserDetails 생성
                List<GrantedAuthority> authorities = new ArrayList<>();
                authorities.add(new SimpleGrantedAuthority("ROLE_"+claims.get("role")));
                UserDetails userDetails = new User(claims.getSubject(), "", authorities);
                Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities());
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
            filterChain.doFilter(servletRequest,servletResponse);
        }catch (AuthenticationServiceException e){
            HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
            httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
            httpServletResponse.setContentType("application/json");
            httpServletResponse.getWriter().write(ResponseDTO.responseErrorMassage(HttpStatus.UNAUTHORIZED, e.getMessage()).toString());
        }
    }
}
  • InitialDataLoader
@Component
public class InitialDataLoader implements CommandLineRunner {
    // CommandLineRunnerλ₯Ό 톡해 μŠ€ν”„λ§λΉˆμœΌλ‘œ λ“±λ‘λ˜λŠ” μ‹œμ μ— run λ©”μ„œλ“œ μ‹€ν–‰
    private final MemberRepository memberRepository;
    private final PasswordEncoder passwordEncoder;
    public InitialDataLoader(
            MemberRepository memberRepository,
            PasswordEncoder passwordEncoder
    ) {
        this.memberRepository = memberRepository;
        this.passwordEncoder = passwordEncoder;
    }
    @Override
    public void run(String... args) throws Exception {
        if(memberRepository.findByEmail("admin@test.com").isEmpty()){
            Member adminMember = Member.builder()
                    .name("admin")
                    .email("admin@test.com")
                    .password(passwordEncoder.encode("1234"))
                    .role(Role.ADMIN)
                    .build();
            memberRepository.save(adminMember);
        }
    }
}
  • SecurityConfig
@Configuration
@EnableWebSecurity
//@EnableGlobalMethodSecurity(prePostEnabled = true) // 6.* λΆ€ν„°λŠ” μžλ™μœΌλ‘œ true μ„€μ •
public class SecurityConfig {
    private final JwtAuthFilter jwtAuthFilter;
    @Autowired
    public SecurityConfig(JwtAuthFilter jwtAuthFilter) {
        this.jwtAuthFilter = jwtAuthFilter;
    }
    @Bean
    public PasswordEncoder passwordEncoder(){
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception{
        return httpSecurity
                .csrf(AbstractHttpConfigurer::disable)   //  6.* λΆ€ν„°λŠ” csrf() 이 사라진닀.
                .cors(cors -> cors.configurationSource(CorsConfig.corsConfigurationSource()))
                .httpBasic(AbstractHttpConfigurer::disable)
                // 접속 URL μ„€μ •
                .authorizeHttpRequests(authorizeRequest ->
                        authorizeRequest
                                .requestMatchers(
                                        "/",
                                        "api/member/create",
                                        "api/doLogin",
                                        "api/items",
                                        "api/item/image/**",
                                        "api/login",
                                        "/login"
                                        )
                                    .permitAll()
                                /*
                                 ROLE_은 뢙이면 μ•ˆ λœλ‹€. hasAnyRole()을 μ‚¬μš©ν•  λ•Œ μžλ™μœΌλ‘œ ROLE_이 λΆ™κΈ° λ•Œλ¬Έμ΄λ‹€.
                                 */
                                .requestMatchers("/manager/**")
                                    .hasAnyRole("ADMIN")
                                .anyRequest()
                                    .authenticated()
                )
                .sessionManagement((sessionManagement) ->
                        sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                )
                .formLogin((formLogin) -> {
                    /* κΆŒν•œμ΄ ν•„μš”ν•œ μš”μ²­μ€ ν•΄λ‹Ή url둜 λ¦¬λ‹€μ΄λ ‰νŠΈ */
                    // formLogin.loginPage("/login");
                })
                .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
                .build();
    }
}
클래슀λͺ… μ„€λͺ…
JWTprovider JWT 토큰을 μƒμ„±ν•˜λŠ” 클래슀
JwtAuthFilter JWT 토큰을 κ²€μ¦ν•˜κ³  μ‚¬μš©μž 인증을 μ²˜λ¦¬ν•˜λŠ” ν•„ν„°
InitialDataLoader μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ‹œμž‘ μ‹œ 초기 데이터λ₯Ό λ‘œλ“œν•˜λŠ” 클래슀
SecurityConfig Spring Security 섀정을 λ‹΄λ‹Ήν•˜λŠ” 클래슀

λ‚˜μ€‘μ— λ‹€μ‹œ 정리할 것.


Spring μ‹€μŠ΅ github 링크

profile
503 Service Unavailable Error

0개의 λŒ“κΈ€