이번에 캡스톤디자인 하면서 킥보드 어플에 사용하는 로그인 기능으로 SpringSecurity를 처음 사용해보았고 거기에 JWT를 함께 사용했다.
기존에 내가 사용하던 방법은 스프링의 인터셉터기능을 이용하는 방식이었으나, 이번에 만드는 웹서버는 REST API서버이기에 해당 방식이 더 어울릴 것 같아 로그인 로직을 새로 구성하였다.
그래서 이 기능에 대해 설명해보려고 한다.
스프링 진영에서 보안을 위해 사용하는 방법들은 여러가지가 존재한다.
이렇게 다양한 방법들이 존재하는데 이번에 알아볼 것은 Spring Security이다.
Spring Security는 JAVA 기반의 애플리케이션에서 보안 기능을 추가하기 위한 인증 및 접근 제어 프레임워크
주로 웹 애플리케이션의
인증(Authentication)과 권한 부여(인가)(Authorization)를 관리하는 데 사용
Spring Security는 개발자들이 XML이나 어노테이션을 통해 선언적으로 보안 요구사항을 관리할 수 있도록 설계
폼 기반 인증, LDAP, OAuth2와 같은 다양한 인증 메커니즘 지원
-> 유연성 제공
메서드 수준에서의 세밀한 보안 정책 설정부터, URL기반의 접근 제어까지, 매우 사엣한 보안 정책 적용 가능
스프링 부트와 결합되었을 때 아주 강력하고 빠르고 쉽게 활용 가능
기본 설정에선 스프링 시큐리티가 모든 요청에 대한 인증 요구
-> 개발자는 이를 자유롭게 커스터마이즈 하여 세밀하게 조정 가능
결론
- 자바 기반의 애플리케이션 보안을 위한 프레임워크
- 개발자들에게 사용하기 쉽고 유연한 보안 설정 옵션을 제공
- 안전한 애플리케이션 구축을 가능하게 한다
- 다양한 보안 요구 사항에 대응할 수 있는 풍부한 기능 보유
- 애플리케이션의 보안을 한 단계 끌어올리는 데 있어 필수적인 도구
여기서 인증과 인가의 차이점에 대해 제대로 짚어보고 가면 좋을것 같다.
인증
인가
차이점
보안이 중요한 모든 시스템에서 이 두 과정은 서로 보완적으로 작동
올바른 사용자만이 적절한 자원에 접근하고 작업을 수행할 수 있도록 해준다

이전에 스터디할 때 잠깐 알아본 적이 있는데, 사실 그때는 그렇게 관심있던 부분이 아니었어서 어쩌면 성의없게 알아본 면이 있다.
그래서 이번에 제대로 알아보자
JWT(Json Web Token)는 웹 표준으로서 두 개체 사이에서 JSON객체를 사용하여 가볍고 자가수용적인 방식으로 정보를 안전하게 전송하기 위한 컴팩트하고 독립적인 방식을 정의한다.
솔직히 말이 좀 어렵다
간단하게 JWT는 말 그대로 웹에서 사용되는 JSON형식의 토큰에 대한 표준 규격으로, JSON객체에 인증에 필요한 정보들을 담은 후 비밀키로 서명한 토큰이다.
이 토큰은 정보를 안전하게 전송할 뿐 아니라, 해당 정보가 변조되지 않았음을 검증할 수 있는 메커니즘도 포함하고 있다.
JWT는 주로 사용자 인증 및 정보 교환에 사용된다.

JWT는 세 부분으로 구성된다 헤더(Header)/페이로드(Payload)/서명(Signature)
대표적인 서명 알고리즘: RS256(공개키/개인키), HS256(비밀키(대칭키))
예를 들어
그런 다음 이 JSON은 Base64Url로 인코딩 되어 JWT의 첫 번째 부분 구성
그런 다음 페이로드는 Base64Url 로 인코딩되어 JSON 웹 토큰의 두 번째 부분을 구성

그러면 왜 JWT를 사용할까?
이전에 공부했던 내용 중 HTTP에 대한 내용을 보면
HTTP의 특성 중 connectionless와 stateless가 있다.
즉 HTTP는 연결을 유지하지 않으며, 상태 또한 유지하지 않는다는 것이다.
그래서 이것이 JWT와 무슨 관련이 있느냐?
JWT를 결국 "로그인"이라는 과정을 위해 사용하는데, 이 "로그인"이라는 과정은 서버-클라이언트간 데이터를 주고 받는 통신 방법이 필요하고, 그 통신 방법이 HTTP이다.
이러한 특성들 때문에 우리가 "로그인"을 구현하는데 많은 어려움을 겪는다.
자신이 누구인지 계속해서 인증해야 하는 것
매번 서버에 사용자가 누구인지 인증을 하는 과정은 번거롭고 귀찮을 뿐만 아니라
매번 요청을 보내야 하기 때문에 우리의 웹페이지가 느려지는 원인이 된다.
위의 원인과 이유로 우리는
사용자가 누구인지 계속해서 인증을 하는 방법 대신
다른 로그인 정보를 유지시킬 방법이 필요했다.
그리고 그 방법 중 하나가 바로 JWT이다.
다른 방법으로 세션도 있으나 이 둘의 비교는 추후에 알아보도록 하자
2가지의 방법이 존재한다
Only Access Token(액세스 토큰만 사용)

With Refresh Token(액세스 토큰 + 리프레시 토큰)
위의 방식으로 했을 때 문제점은 Access Token을 탈취 당했을 때이다.
유효기간이 긴 토큰이라면 그 기간동안 탈취한 사람은 계속해서 사용할 수 있다.
그래서 또 유효기간을 줄이자면 사용자가 로그인을 여러 번해야 하는 번거로움이 있다.
그래서 나온것이 Refresh Toekn이다
Refresh Token역시 Access Token과 같은 JWT인데,
로그인을 했을 때 서버에서 이 둘을 동시에 보내준다
단, 둘의 유효기간을 다르게 해서 보낸다.
Refresh Token을 한 달, Access Toekn을 하루로 잡았다면
Access Token의 기간이 다 되어도 Refresh Token의 기간이 남아있기 때문에
사용자는 로그인 없이 다시 Access Token을 발급 받을 수 있다.
내가 이번 캡스톤 디자인에서 사용한 방식은 첫 번째 방식이다.
장점
단점
Spring Security와 JWT를 결합하는 것은 인증 및 인가 과정을 관리하기 위한 매우 효과적인 방법이다.
SpringSecurity는 강력한 보안 프레임워크 제공
이 결합을 통해, 개발자들은 안전하고 확장 가능한 인증 시스템 손쉽게 구축
우선 의존성부터 각각 추가
Spring Security 설정
Spring Security를 사용해서 인증 메커니즘을 설정한다
스프링 부트 3.1.X ~ (스프링 6.1.X ~ )의 경우
public class SpringSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((auth) -> auth
.requestMatchers("/login", "/join").permitAll()
.anyRequest().authenticated()
);
return http.build();
}
}
그 외의 버전의 경우 버전 별 SpringSecurity 참고
Spring Security와 JWT를 결합함으로써, 개발자들은 강력하고 유연한 인증 시스템을 구축할 수 있으며, 애플리케이션의 보안성을 크게 향상시킬 수 있다.
이번 프로젝트에선 단방향으로 Access Token만 사용 하는 방식으로 구현하였는데, 다음에는 Refresh토큰을 같이 사용하는 방식으로 프로젝트를 하나 제작하려고 한다
이 두 가지 모두 처음 사용하는 것이라 많이 어색하고 어려움이 있었지만, 차근차근 도입해가면서 어느정도 이해가 된 것 같다.
참고
https://velog.io/@chuu1019/%EC%95%8C%EA%B3%A0-%EC%93%B0%EC%9E%90-JWTJson-Web-Token