- 강의
- 113강(Spring Security v3) ~ 117강(wrap-up)
Spring Security
- Java 기반 보안 프레임워크
- 기능
- 인증Authentication) : 신원 확인
- 권한 부여(Authorization ) : 특정 자원이나 작업에 대한 접근 권한 확인
- 세션 확인 : 사용자 세션 보호, 동시 세션 제어, 세션 고정 보호 등의 기능 제공
- CSRF 방지 : CSRF 공격 방지 기능 제공
- 인증
- Authentication
- 유저 확인
- 인가
- Authorization
- 유저 권한 확인 및 허가
- 로그인 인증 처리 과정
- AuthenticationFilter, UserDetails, UserDetailsService 구현하기
- 설정
- 의존성 추가
implementation 'org.springframework.boot:spring-boot-starter-security'
- 의존성만 추가한 경우
- 포스트맨의 Basic Auth에 {username : root, password : 아래 생성된 값 } 넣으면 동작됨
- 구현하기
- AuthenticationFilter
- JwtTokenProvider : JWT를 생성하고, 검증하며, JWT로부터 인증 정보를 추출하는 역할
- JwtAuthenticationFilter : HTTP 요청을 가로채 JWT를 확인하고, 이를 통해 인증 정보를 추출하여 SecurityContext에 설정하는 역할
- UserDetails : UserDetails 인터페이스를 상속 받아서 구현하기
- getAuthorities : 권한 가져오기
- getPassword : 패스워드 설정 , 유저 인증할 때 사용
- getUsername : 유저 ID 정보, 유저 인증할 때 사용
- UserDetailsService : UserDetailsService 인터페이스를 상속 받아서 구현하기
- loadUserByUsername : username에 해당하는 사용자를 찾아서 userdetail 객체 생성해서 반환하기
- AuthenticationFilter
보안지식
XSS
- Cross Site Scripting
- 사용자가 웹 페이지에 악성 스크립트 삽입을 통한 해킹
- 의도적인 스크리팁 삽입을 통해서 쿠키 보내기 설정되고, 이를 통해서 서버 해킹이 발생
- 방지 방법
- 글 작성 시 스크립트 등록을 못하도록 설정
- 중요한 Cookie HTTPOnly 및 Secure 설정
CSRF
- Cross Site Request Forgery
- 사용자의 세션이나 토큰을 이용해서 다른 명령 실행하기
- 방지 방법
- HTTP의 Referer이나 HOST 이름 비교
- CAPTCHA를 통해서 사람인지 확인
SQL Injection
- 서버 요청 시 악의적인 DB SQL문을 주입하는 해킹 방법
- 방지 방법
- 여러 IF문을 통한 검증 로직 추가
- JPA 사용
SOP
- Same Origin Policy
- 브라우저는 기본적으로 SOP 사용
- 외부에서 얻은 데이터는 항상 같은 Origin이어야함
Origin
- 출처
- 동일한 origin 판단 여부 : URI의 Protocol + Host + Port가 동일해야 함
- ex) http://example.com과 http://example.com:8080은 다른 origin임
CORS
- Cross-Origin Resource Sharing
- front-end와 back-end 소통 시 발생할 수 있는 문제
- 해결방법
- 브라우저 플러그인
- 백엔드 전역 보안 설정
- 실습 - CORS 브라우저 플러그인
- 실습 - CORS 백엔드 전역 보안 설정
package com.github.supercodingspring.config.security;
import com.github.supercodingspring.web.filters.JwtAuthenticationFilter;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.util.Arrays;
import java.util.List;
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfiguration {
private final JwtTokenProvider jwtTokenProvider;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.headers().frameOptions().sameOrigin()
.and()
.formLogin().disable()
.csrf().disable()
.cors().configurationSource(corsConfigurationSource()) // CORS 설정
.and()
.httpBasic().disable()
.rememberMe().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/resources/static/**", "/v1/api/sign/*").permitAll()
.antMatchers("/v1/api/air-reservation/*").hasRole("USER")
.and()
.exceptionHandling()
.authenticationEntryPoint(new CustomAuthenticationEntryPoint())
.accessDeniedHandler(new CustomerAccessDeniedHandler())
.and()
.addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
@Bean
public CorsConfigurationSource corsConfigurationSource(){
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(List.of("http://localhost:63342"));
configuration.setAllowCredentials(true); // token 주고 받을 때,
configuration.addExposedHeader("X-AUTH_TOKEN"); // token
configuration.addAllowedHeader("*");
configuration.setAllowedMethods(Arrays.asList("GET", "PUT", "POST", "PATCH", "DELETE", "OPTIONS"));
configuration.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
- 환경변수
- 서버 코드에서 공개되면 안되는 코드를 환경변수로 설정해서 사용함
- 설정 방법
- 로컬 컴퓨터 '환경변수'
- 코드에서는 환경변수로 실제 값 숨기기
- @ConfigurationProperties : 여러 개의 환경변수를 한번에 가져올 때 사용
- @Value : 한 개의 환경변수를 가져오기 위해서 사용
// application.yml
datasource:
username: 123
password: 1234
// build.gradle
dependencies {
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
}
// 가져오기.java
@Getter
@Setter
@ConfigurationProperties(prefix = "datasource")
public class DataSourcePropertries {
private String username;
private String password;
}
// 사용하기.java
@EnableConfigurationProperties(DataSourcePropertries.class)
@RequiredArgsConstructor
public class JdbcConfig {
private final DataSourcePropertries dataSourcePropertries;
public void test() {
System.out.println("username : " + dataSourcePropertries.getUsername());
}
}
// application.yml
jwt:
secret-key-source : ${JWT_SECRET_KEY}
// 환경변수 설정 사용하기
public class JwtToeknProvider {
@Value("${jwt.secret-key-source}")
private String secreKey;
}
Spring 커리큘럼 확인하기
'슈퍼코딩 > 주특기(JAVA)' 카테고리의 다른 글
2024.06.21(금) 슈퍼코딩 프로젝트1 2주차 Day 5 후기 (0) | 2024.06.21 |
---|---|
슈퍼코딩 신입연수원 10주차 후기 (0) | 2024.06.08 |
2024.06.06(목) 슈퍼코딩 신입연수원 10주차 Day 4 후기 - Cache, Cookie & Session & JWT (1) | 2024.06.06 |
2024.06.05(수) 슈퍼코딩 신입연수원 10주차 Day 3 후기 - 테스팅, 서버 업무, 서블릿 컨테이너, filter, interceptor (0) | 2024.06.05 |
2024.06.04(화) 슈퍼코딩 신입연수원 10주차 Day 2 후기 - JPA, PSA (0) | 2024.06.04 |