5. 스프링 시큐리티를 활용한 보안 강화
5.1. 비밀번호 저장 전략
비밀번호 저장 전략은 사용자의 비밀번호를 안전하게 저장하기 위한 방법입니다. 애플리케이션에 저장되는 비밀번호는 해싱(hash)과 솔트(salt)를 이용하여 암호화되어 저장됩니다.
- 해싱: 비밀번호를 일정한 길이의 문자열로 변환하는 알고리즘입니다. 해싱을 통해 원본 비밀번호를 유추하기 어렵게 만듭니다. SHA-256, BCrypt, SCrypt 등 다양한 해싱 알고리즘이 존재합니다.
- 솔트: 해싱 과정에서 사용되는 무작위 문자열로, 같은 비밀번호라도 솔트 값이 다르면 다른 해시 값이 생성됩니다. 이를 통해 무차별 대입 공격(brute force attack)을 방어합니다.
예제 코드 (비밀번호 저장 전략 설정)
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
// ...
}
5.2. OAuth2 및 JWT 사용
OAuth2는 인증을 위한 업계 표준 프로토콜입니다. JWT(JSON Web Token)는 클레임(claim)을 JSON 객체로 표현한 토큰입니다. OAuth2와 JWT를 사용하여 사용자 인증 및 API 인가를 처리할 수 있습니다.
- OAuth2는 Authorization Server, Resource Server, Client, User 네 가지 주요 구성 요소로 이루어져 있습니다.
- Authorization Server는 클라이언트의 인증 및 인가 요청을 처리하고, JWT를 발급합니다.
- Resource Server는 클라이언트가 보호된 리소스에 접근할 때, JWT를 검증하고 리소스에 대한 접근을 허용합니다.
예제 코드 (OAuth2 및 JWT 설정)
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Autowired
private JwtAccessTokenConverter accessTokenConverter;
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.tokenStore(new JwtTokenStore(accessTokenConverter));
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/api/**").authenticated()
.and()
.exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
}
}
5.3. 메서드 수준의 보안 적용
메소드메서드 수준의 보안은 특정 메서드에 대해서만 특정 권한을 가진 사용자가 접근할 수 있도록 제한합니다. 스프링 시큐리티에서는 @PreAuthorize, @PostAuthorize, @Secured 등의 애너테이션을 사용하여 메서드 수준의 보안을 적용할 수 있습니다.
- @PreAuthorize: 메소드가 실행되기 전에 권한을 검사합니다. 조건식을 사용하여 권한을 정의할 수 있습니다.
- @PostAuthorize: 메소드가 실행된 후에 권한을 검사합니다. 반환된 객체에 대한 접근 권한을 검사하는 데 유용합니다.
- @Secured: 메소드메서드 수준의 보안을 적용하는 간단한 방법입니다. 클래스 또는 메서드에 직접 권한을 지정합니다.
예제 코드 (메소드 수준의 보안 적용)
@Service
public class UserService {
@PreAuthorize("hasRole('ADMIN')")
public void deleteUser(Long userId) {
// 사용자 삭제 로직
}
@PostAuthorize("returnObject.username == principal.username")
public User getUser(Long userId) {
// 사용자 조회 로직
return user;
}
@Secured("ROLE_USER")
public List<User> getAllUsers() {
// 모든 사용자 조회 로직
return userList;
}
}
2023.05.05 - [프로그래밍/스프링부트(Spring Boot) 기초부터 ~] - [스프링 부트(SpringBoot) : 중급] RESTful API 개발 심화
반응형
'GD's IT Lectures : 기초부터 시리즈 > 스프링부트(Spring Boot) 기초부터 ~' 카테고리의 다른 글
[스프링 부트(SpringBoot) : 중급] 클라우드 환경에서의 배포 (0) | 2023.05.05 |
---|---|
[스프링 부트(SpringBoot) : 중급] 테스트 전략 및 심화 (0) | 2023.05.05 |
[스프링 부트(SpringBoot) : 중급] RESTful API 개발 심화 (0) | 2023.05.05 |
[스프링 부트(SpringBoot) : 중급] 웹 개발 심화 (0) | 2023.05.05 |
[스프링 부트(SpringBoot) : 중급] 데이터베이스 연동 심화 (0) | 2023.05.05 |
댓글