Spring Security와 React 인증 구현 정리
스프링 부트와 리액트틀 이용하여 서버 - 클라이언트 구조를 만들고, 스프링 시큐리티를 이용하여 로그인하는 기능을 만든다. 내용이 방대하기 때문에 천천히 하나씩 설명해나가려고 한다. 우선 전체적인 느낌만 살펴본다.
1. 기본 설정
SecurityConfig 설정
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/v1/products").permitAll()
.requestMatchers("/api/v1/orders/**").authenticated()
.requestMatchers("/api/v1/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
);
return http.build();
}
}
CORS 설정
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost:3000"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
2. 사용자 인증 처리
CustomUserDetailsService
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
return org.springframework.security.core.userdetails.User.builder()
.username(user.getUsername())
.password(user.getPassword())
.roles(user.getRole().name())
.build();
}
}
3. 인증 흐름 순서
- 사용자가 React 앱에서 로그인 시도
- Spring Security의 인증 필터가 요청 처리
- CustomUserDetailsService가 사용자 정보 로드
- 비밀번호 검증 (PasswordEncoder 사용)
- 인증 성공/실패 응답 전송
4. React에서의 구현
로그인 컴포넌트
function LoginForm() {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const handleSubmit = async (e) => {
e.preventDefault();
try {
const response = await fetch('/login-process', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `username=${username}&password=${password}`,
credentials: 'include'
});
if (response.ok) {
// 로그인 성공 처리
}
} catch (error) {
// 에러 처리
}
};
}
권한에 따른 UI 렌더링
function Dashboard() {
const [userInfo, setUserInfo] = useState(null);
useEffect(() => {
axios.get('/api/user-info')
.then(response => setUserInfo(response.data));
}, []);
return (
<div>
{userInfo?.role === 'ROLE_ADMIN' && (
<button>관리자 기능</button>
)}
</div>
);
}
5. 보안 고려사항
- HTTPS 사용 권장
- CSRF 보호 설정
- 적절한 비밀번호 인코딩
- 세션 관리
- 권한 기반 접근 제어
- 허용된 출처에서만 API 접근 가능
6. 중요 포인트
- Spring Security가 인증 처리를 자동으로 수행
- React는 세션 쿠키를 통해 인증 상태 유지
- 모든 API 요청은 인증된 세션을 통해 처리
- 권한에 따른 기능 접근 제어 가능
- CORS 설정으로 허용된 클라이언트만 접근 가능
'스프링' 카테고리의 다른 글
스프링 - REST API (0) | 2024.12.17 |
---|---|
스프링 시큐리티 - 간단한 인증절차 정리 (0) | 2024.12.16 |
스프링 - 트랜잭션 이해 (2) (0) | 2024.12.13 |
스프링 파라미터 처리 과정 (0) | 2024.12.12 |
스프링 - 스프링 (0) | 2024.12.09 |
댓글