SpringBoot Security를 사용하는 이유?
SpringBoot 애플리케이션에서 보안을 구현할 때 사용됩니다.
인증, 권한 부여, 보안 설정 등의 주요 기능을 구현하며 애플리케이션의 보안을 효율적으로 관리할 수 있도록 도와주기 때문에
상당한 보안 지식과 경험이 있지 않다면 보안을 직접 구현하는 대신 Spring Security라는 검증된 프레임워크를 사용함으로써 보안을 강화할 수 있습니다.
주요기능
1. 인증 (Authentication): 로그인
- 폼 기반 인증: 주로 HTML 로그인 폼을 통해 사용자 이름과 비밀번호를 서버에 제출하는 방식
Step1. 로그인 페이지 폼에서 사용자 자격 증명 제출
사용자가 로그인 폼에 사용자 이름과 비밀번호를 입력하고 제출하면
클라이언트는 POST 요청을 통해 자격 증명을 서버로 전송합니다.
<form method="post" action="/login">
<input type="text" name="username" placeholder="Username">
<input type="password" name="password" placeholder="Password">
<button type="submit">Login</button>
</form>
Step2. 서버 검증
DB나 다른 인증 소스를 통해 사용자를 검증합니다.
Step3. 인증 성공/실패 처리
- 인증 성공 → 성공시 보여질 페이지로 리다이렉트
- 인증 실패 → 오류 메시지를 포함하여 다시 로그인 페이지로 리다이렉트
- JWT (JSON Web Token) 인증: JWT 토큰 기반 인증 방식
Step1. 사용자 로그인 요청
사용자가 로그인 자격 증명을 서버에 제출합니다. 일반적으로 JSON 형식의 POST 요청으로 전달됩니다.
[Request Body]
POST /login
Content-Type: application/json
{
"username": "user",
"password": "password"
}
Step2. JWT 발급
서버에서 사용자 인증을 통해 자격 증명을 검증하고 검증이 성공하면 JWT 생성 후 클라이언트에 반환합니다.
[Response Body]
HTTP/1.1 200 OK
Content-Type: application/json
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
}
Step3. 클라이언트가 보호된 리소스 요청 시 JWT 포함
클라이언트는 보호된 리소스에 접근할 때, Authorization 헤더에 JWT를 포함하여 요청합니다.
[Request Header]
GET /api/protected-resource
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Step4. 서버에서 JWT 검증 및 리소스 제공
서버는 JWT를 검증하고, 유효한 토큰이면 보호된 리소스를 제공합니다. 검증 과정에서는 토큰의 서명, 유효 기간(exp), 사용자 정보(sub) 등을 확인합니다.
HTTP/1.1 200 OK
Content-Type: application/json
{
"data": "This is protected data"
}
- OAuth2 인증: 외부 인증 제공자(Google, Facebook 등)를 통해 인증하는 방식
Step1. 클라이언트 등록
OAuth2 제공자(예: Google, Facebook 등)에 등록하여 클라이언트 ID와 클라이언트 비밀 키를 받습니다.
Step2. 권한 요청
사용자가 애플리케이션을 통해 OAuth2 제공자에게 자신의 자원에 접근할 수 있는 권한을 요청합니다. 이 과정에서 사용자에게 권한 요청 화면이 표시됩니다.
Step3. 사용자 승인
사용자는 권한 요청 화면에서 애플리케이션이 요청한 권한을 승인하거나 거부합니다.
Step4. 권한 부여 코드 반환
사용자가 권한을 승인하면, OAuth2 제공자는 권한 부여 코드를 애플리케이션에 반환합니다. 이 코드는 클라이언트가 액세스 토큰을 요청할 때 사용됩니다.
HTTP/1.1 302 Found
Location: REDIRECT_URI?code=AUTHORIZATION_CODE&state=STATE
Step5. 액세스 토큰 요청
애플리케이션은 반환된 권한 부여 코드를 사용하여 OAuth2 제공자에게 액세스 토큰을 요청합니다.
POST /token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=AUTHORIZATION_CODE
&redirect_uri=REDIRECT_URI
&client_id=CLIENT_ID
&client_secret=CLIENT_SECRET
Step6. 액세스 토큰 반환
OAuth2 제공자는 유효한 요청에 대해 액세스 토큰을 반환합니다. 이 토큰은 보호된 자원에 접근할 때 사용됩니다.
HTTP/1.1 200 OK
Content-Type: application/json
{
"access_token": "ACCESS_TOKEN",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "REFRESH_TOKEN"
}
Step7. 보호된 자원 요청
애플리케이션은 획득한 액세스 토큰을 사용하여 보호된 자원에 접근합니다. 이 토큰은 HTTP 요청의 Authorization 헤더에 포함됩니다.
GET /api/protected-resource
Authorization: Bearer ACCESS_TOKEN
Step8. 자원 제공
서버는 액세스 토큰의 유효성을 검사하고, 유효한 토큰이면 요청된 자원을 반환합니다.
- HTTP Basic 인증: HTTP 헤더를 통해 사용자 이름과 비밀번호를 전달하여 인증하는 방식
Step1. 클라이언트 요청
인증 요청 시 클라이언트가 HTTP 헤더에 Authorization 헤더를 포함시켜 사용자 이름과 비밀번호를 Base64로 인코딩하여 GET이나 POST 메소드로 서버에 전달합니다.
GET /api/protected-resource HTTP/1.1
Host: example.com
Authorization: 사용자이름(Basic) 인코딩된사용자비밀번호(dXNlcm5hbWU6cGFzc3dvcmQ=)
POST /api/protected-resource HTTP/1.1
Host: example.com
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
Content-Type: application/json
{
"key": "value"
}
Step2. 서버 검증
서버는 이 Authorization 헤더를 읽고, Base64로 인코딩된 문자열을 디코딩하여 사용자 이름과 비밀번호를 추출해 DB나 다른 인증 소스를 통해 검증합니다.
Step3. 서버 응답
인증이 성공하면, 서버는 보호된 리소스에 접근을 허용하고, 일반적으로 별도의 인증 토큰을 생성하지 않습니다.
인증이 실패하면, 서버는 401 Unauthorized 응답을 반환합니다.
{
"status": "success",
"message": "Authenticated successfully"
}
별도의 세션 관리나 토큰 발급이 필요 없어 간단하지만, Base64 인코딩은 단순히 데이터를 인코딩하는 것일 뿐, 암호화가 아니기 때문에 반드시 HTTPS를 사용하여 데이터를 암호화해야 합니다. 주로 간단한 RESTful API나 테스트 환경에서 사용됩니다.
- LDAP 인증: LDAP 디렉토리 서비스를 통해 인증하는 방식
2. 권한 부여 (Authorization): 접근 권한 확인
관리자/일반 사용자 등 사용자에게 할당된 역할에 따라 접근 권한을 부여하기 위해 아래와 같은 방식의 접근 제어를 사용할 수 있습니다.
- URL 기반 접근 제어: URL 패턴을 기반으로 접근 권한을 설정
- 주로 HttpSecurity를 사용하여 설정합니다.
- 예: /admin/** 경로는 관리자만 접근 가능, /user/** 경로는 일반 사용자만 접근 가능.
- 메서드 기반 접근 제어: 특정 메서드에 대해 접근 권한을 설정
- 주로 어노테이션(@PreAuthorize, @Secured, @RolesAllowed)을 사용하여 설정합니다.
- 예: manageUsers() 메서드는 관리자만 접근 가능, viewProfile() 메서드는 일반 사용자만 접근 가능.
3. 보안 설정 (Security Configuration)
애플리케이션 전반에 걸친 보안 정책을 정의하고 구성하는 것입니다.
Spring Boot Security는 WebSecurityConfigurerAdapter를 상속하여 커스텀 보안 설정을 쉽게 할 수 있습니다.
- CSRF 보호: Cross-Site Request Forgery 공격을 방지하기 위해 CSRF 토큰을 사용
- 세션 관리: 세션 고정 보호, 세션 타임아웃 설정 등을 통해 세션을 관리
- 로그인/로그아웃 설정: 커스텀 로그인 페이지, 로그인 성공/실패 처리, 로그아웃 설정 등
🤔 SpringBoot Security에 대해 공부 하기 전 궁금증들
Springboot Security를 꼭 사용해야 할까?
첫째도 둘째도 보안!
보안이 중요하기 때문에 Spring Security보다 보안을 강화할 수 있다는 자신이 있는게 아니면 로그인/회원가입 기능을 구현할 땐 필수적으로 사용해야한다!
그래서 Springboot Security가 뭘 하는건데?
로그인할 때 토큰 받아서 인증하고 소셜 로그인 할 때 토큰 주고 받고 하는 인증부터 일반 사용자와 관리자 구분해주는 권한 부여, 보안 설정을 통한 세션 관리까지! 로그인과 관련된 대부분의 작업을 한다고 생각하면 될 것 같다.
로그인 인증 방식 이해하기 너무 복잡해!!
폼 기반 인증, JWT 인증, OAuth2 인증, HTTP Basic 인증에 대해 정리하면서 어느정도 로그인 인증 방식 자체에 대한 개념이 잡혔다.
각 단계별 Request와 Response 예시가 큰 도움이 된 것 같다.
백견이불여일행! 빨리 직접 구현해보면서 내가 얼마나 이해 했는지 알아봐야겠다.
JWT, OAuth2 뭔지 들어는 봤는데 너무 복잡하고 정확히 어떤 일을 처리하는지 모르겠다
JWT는 서버에서 토큰을 발급해주는 거고, OAuth2는 소셜 로그인을 통해 토큰 받는거!
인증 구현하고 소셜 로그인 연결하는게 다른 것들에 비해 확실히 복잡한 것 같지만 프로젝트 개발에 회원 관리는 필수이기 때문에 이 부분을 잘 해두면 굉장히 도움될 것 같다.
😆 궁금증들 해결 완료!
이어지는 궁금증들은.. 다음 글에서 해결!
JWT는 토큰을 처리하는거고 OAuth2는 소셜 로그인을 처리하는건데 두 개를 어떻게 같이 사용하는거지?
OAuth2를 통한 회원가입은 DB에 어떻게 넣어야 하는걸까?
일반 회원가입과 같은 테이블을 사용해서 어떻게 관리하지?