폼 인증
• HTTP 기반의 폼 로그인 인증 메커니즘을 활성화하는 API 로서
사용자 인증을 위한 사용자 정의 로그인 페이지를 쉽게 구현할 수 있다
• 기본적으로 스프링 시큐리티가 제공하는 기본 로그인 페이지를 사용하며
사용자 이름과 비밀번호 필드가 포함된 간단한 로그인 양식을 제공한다
• 사용자는 웹 폼을 통해 자격 증명(사용자 이름과 비밀번호)을 제공하고
Spring Security는 HttpServletRequest에서 이 값을 읽어 온다
클라이언트가 아직 접근 인증을 받지 못했다면 접근 예외가 발생하고 예외 처리 필터로 인해 인증이 시작되면서 로그인 페이지로 리다이렉트 된다.
formLogin() API
[메소드를 API라고 칭하는 이유는 이 메서드들이 Spring Security의 내부 기능에 접근할 수 있는 인터페이스 역할을 하기 때문인거같다. 내가 아는 일반적인 API는 아님.]
• FormLoginConfigurer 설정 클래스를 통해 여러 API 들을 설정할 수 있다
• 내부적으로 UsernamePasswordAuthenticationFilter 가 생성되어 폼 방식의 인증 처리를 담당하게 된다
예시코드
package com.example.security_inflearn;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import java.io.IOException;
@EnableWebSecurity
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http, HttpSecurity httpSecurity) throws Exception{
http.authorizeHttpRequests(auth-> auth.anyRequest().authenticated())
.formLogin(form -> form // formLoginConfigurer를 받아서 설정
.loginPage("/loginPage")
.loginProcessingUrl("/loginProc")
.defaultSuccessUrl("/",true)
.failureUrl("/failed")
.usernameParameter("userId") // form 형식에서 넘어오는 유저아이디 input 파라미터이름 설정
.passwordParameter("passwd")
.successHandler(new AuthenticationSuccessHandler() { // 성공 핸들러 익명클래스 구현
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
System.out.println("authentication = " + authentication);
response.sendRedirect("/home");
}
})// 익명클래스 구현시 람다로도 가능하다. 실패 핸들러는 Authentication 대신 예외가 넘어온다.
.failureHandler(((request, response, exception) -> {
System.out.println("exception = " + exception);
response.sendRedirect("/login");
}))
.permitAll()
);
return http.build();
}
@Bean
public InMemoryUserDetailsManager inMemoryUserDetailsManager() {
UserDetails user = User.withUsername("user")
.password("{noop}1234")
.authorities("ROLE_USER")
.build();
UserDetails user2 = User.withUsername("user2")
.password("{noop}1234")
.authorities("ROLE_USER")
.build();
UserDetails user3 = User.withUsername("user3")
.password("{noop}1234")
.authorities("ROLE_USER")
.build();
return new InMemoryUserDetailsManager(user);
}
}
테스트용 API추가
@GetMapping("/home")
public String home() {
return "home";
}
@GetMapping("/loginPage")
public String loginPage() {
return "loginPage";
}
localhost:8080 접근시 설정한 로그인 페이지 url로 request 되는것을 확인가능
.loginPage() 설정을 주석처리하고 다시 로그인해보면 [ spring security 기본 로그인폼 페이지를 사용하면]
설정한 로그인처리 url를 request하는것을 확인가능
form에서 전달되는 파라미터명이 설정한대로 넘어오는것을 확인가능
로그인 후 요청되는 url이 .defaultSuccessUrl("/",true)의 설정을 따르는것을 확인가능
[현재 성공핸들러,실패핸들러 설정을 주석처리해둠 ]
usernameParameter() ,passwordParameter() 설정한대로 spring security가 파라미터 명 설정을 해준다.
defaultSuccessUrl("/",false)
다음과 같이 두번째 매개변수를 false 로 둔다면
인증 성공시 인증 요청된 페이지로 돌아가게 된다.
[인증 전에 보안이 필요한 페이지를 방문하다가 인증에 성공한 경우이면 이전 위치로 리다이렉트 됨]
로그인하기전에 http://localhost:8080/home 해당 url 요청하면 로그인페이지로 이동되는데 그때 로그인을 성공하게 되면
다음과 같이 요청한 url로 리다이렉트 되게된다.
.failureUrl("/failed")
실패시 설정한 url로 request된다.
하지만
.successHandler(new AuthenticationSuccessHandler() { // 성공 핸들러 익명클래스 구현
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
System.out.println("authentication = " + authentication);
response.sendRedirect("/home");
}
})// 익명클래스 구현시 람다로도 가능하다. 실패 핸들러는 Authentication 대신 예외가 넘어온다.
.failureHandler(((request, response, exception) -> {
System.out.println("exception = " + exception);
response.sendRedirect("/login");
}))
성공 핸들러, 실패 핸들러를 설정한다면
.defaultSuccessUrl("/",false)
.failureUrl("/failed")
위의 설정은 무시된다. [ 핸들러 설정이 우선시 된다.]
authentication = UsernamePasswordAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=user, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, CredentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[ROLE_USER]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=E04F2616029E67A0A8A40CACBD4920FE], Granted Authorities=[ROLE_USER]]
exception = org.springframework.security.authentication.BadCredentialsException: 자격 증명에 실패하였습니다.
성공했을때 authentication 객체를 출력해본 결과와
실패시 exception 객체를 출력해본 결과이다.
public final class FormLoginConfigurer<H extends HttpSecurityBuilder<H>> extends
AbstractAuthenticationFilterConfigurer<H, FormLoginConfigurer<H>, UsernamePasswordAuthenticationFilter> {
해당 클래스를 이용해서 formLogin 설정을 진행하는것이다.
폼 인증 필터 - UsernamePasswordAuthenticationFilter
• 스프링 시큐리티는 AbstractAuthenticationProcessingFilter 클래스를 사용자의 자격 증명을 인증하는 기본 필터로 사용 한다
• UsernamePasswordAuthenticationFilter 는 AbstractAuthenticationProcessingFilter 를 확장한 클래스로서 HttpServletRequest 에서 제출된 사용자 이름과 비밀번호로부터 인증을 수행한다
• 인증 프로세스가 초기화 될 때 로그인 페이지와 로그아웃 페이지 생성을 위한 DefaultLoginPageGeneratingFilter 및 DefaultLogoutPageGeneratingFilter 가 초기화 된다
AbstractAuthenticationProcessingFilter 를 이용하여 인증처리를 진행한다. [ login같은]
그때 AbstractAuthenticationProcessingFilter의
스프링 security 기본제공 구현체인 UsernamePasswordAuthenticationFilter가 사용될수도있고
사용자가 등록한 CustomAuthenticationFilter가 사용될 수 있다.
Filter를 적용할지 말지 RequestMatcher를 통해 url 검증을 진행해서 filter를 적용해야하는 request라면 인증 진행
필터는 아이디,패스워드를 UsernamePasswordAuthenticationToken에 저장하고 Token을 AuthenticationManager로 전달하고 그걸로 인증 진행
인증에 성공했어도 UsernamePasswordAuthenticationToken를 다시 만들어서
UserDetails [또는 User] , Authorities를 담아준다.
[인증에 성공한 사용자에 대한 정보, 권한등을 담아주는 작업 ]
인증에 성공한 사용자 정보,인증정보를 담고있는 UsernamePasswordAuthenticationToken객체를
SecurityContext에 설정[저장]한다.
[UsernamePasswordAuthenticationToken는 Authentication의 구현체이다.]
SecurityContext에 대해 [ claude]
SecurityContext는 Spring Security의 핵심 컴포넌트 중 하나입니다. 이에 대해 자세히 설명드리겠습니다:
1. 정의:
SecurityContext는 현재 애플리케이션의 보안 컨텍스트에 대한 정보를 보유합니다. 주로 현재 인증된 사용자의 세부 정보를 저장합니다.
2. 주요 역할:
- 현재 인증된 사용자의 정보(Authentication 객체)를 저장합니다.
- 애플리케이션 전반에 걸쳐 현재 사용자의 보안 정보에 접근할 수 있게 해줍니다.
3. 저장 정보:
- 주로 Authentication 객체를 저장합니다. 이 객체는 사용자의 인증 정보, 권한 등을 포함합니다.
4. 사용 방법:
- SecurityContextHolder를 통해 접근할 수 있습니다.
- 예: `SecurityContextHolder.getContext().getAuthentication()`
5. 생명주기:
- 기본적으로 ThreadLocal에 저장되어 요청별로 관리됩니다.
- HTTP 요청이 처리되는 동안 유지되며, 요청 처리가 완료되면 정리됩니다.
6. 보안 중요성:
- 현재 사용자의 보안 정보를 안전하게 보관하고 접근할 수 있게 해주는 중요한 메커니즘입니다.
7. 사용 예시:
java
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();
String username = authentication.getName();
8. 커스터마이징:
- SecurityContextHolder의 전략을 변경하여 SecurityContext의 저장 방식을 커스터마이즈할 수 있습니다.
9. 멀티스레드 환경:
- 기본적으로 ThreadLocal을 사용하므로 멀티스레드 환경에서 안전합니다.
10. 인증 후 처리:
- 성공적인 인증 후, AuthenticationManager는 새로운 Authentication 객체를 SecurityContext에 설정합니다.
SecurityContext는 Spring Security의 핵심 개념 중 하나로, 애플리케이션의 보안 상태를 관리하고 현재 인증된 사용자의 정보를 안전하게 보관하는 중요한 역할을 합니다. 이를 통해 애플리케이션의 어느 부분에서든 현재 사용자의 인증 정보와 권한을 쉽게 확인하고 사용할 수 있습니다.
그리고
세션에 SecurityContext가 저장된다.
Spring Security의 인증 과정[ claude]
1. 인증 요청 시작:
- 사용자가 로그인 폼을 통해 아이디와 비밀번호를 제출합니다.
2. UsernamePasswordAuthenticationToken 생성:
- 제출된 아이디와 비밀번호로 UsernamePasswordAuthenticationToken 객체가 생성됩니다.
- 이 시점에서 토큰은 아직 인증되지 않은 상태입니다.
3. AuthenticationManager에 의한 인증:
- 생성된 토큰은 AuthenticationManager에 전달됩니다.
- AuthenticationManager는 등록된 AuthenticationProvider들을 통해 인증을 시도합니다.
4. 인증 성공 시:
- 인증이 성공하면, 완전히 인증된 UsernamePasswordAuthenticationToken이 생성됩니다.
- 이 토큰에는 사용자의 권한 정보 등이 포함됩니다.
5. SecurityContextHolder를 통한 SecurityContext 설정:
- 인증된 토큰은 새로운 SecurityContext에 저장됩니다.
- SecurityContextHolder.getContext().setAuthentication(authenticatedToken)을 통해 설정됩니다.
- 이로써 현재 스레드에서 인증된 사용자 정보를 사용할 수 있게 됩니다.
6. SessionAuthenticationStrategy 적용:
- 세션 관련 보안 정책을 적용합니다.
- 예를 들어, 동시 세션 제어, 세션 고정 보호 등을 처리합니다.
7. RememberMeServices 처리: -> 로그인 화면에 로그인정보 기억하기 체크박스 같은거
- "Remember Me" 기능이 활성화되어 있다면, RememberMeServices가 호출됩니다.
- 사용자의 인증 정보를 쿠키나 데이터베이스에 저장하여 다음 방문 시 자동 로그인을 지원합니다.
8. ApplicationEventPublisher를 통한 이벤트 발행:
- 인증 성공 이벤트(InteractiveAuthenticationSuccessEvent)를 발행합니다.
- 이를 통해 다른 컴포넌트들이 인증 성공을 인지하고 필요한 작업을 수행할 수 있습니다.
9. AuthenticationSuccessHandler 실행:
- 인증 성공 후의 추가적인 처리를 담당합니다.
- 예를 들어, 성공 페이지로의 리다이렉션, 로그 기록 등을 수행할 수 있습니다.
10. SecurityContext의 저장:
- 인증이 완료된 SecurityContext는 일반적으로 HTTP 세션에 저장됩니다.
- 이는 SecurityContextPersistenceFilter에 의해 관리됩니다.
11. 응답 반환:
- 인증 과정이 모두 완료되면, 클라이언트에게 적절한 응답이 반환됩니다.
- 일반적으로 성공 페이지로 리다이렉션되거나, JWT 토큰 등이 반환될 수 있습니다.
이 과정에서 각 컴포넌트의 역할은 다음과 같습니다:
- UsernamePasswordAuthenticationToken: 사용자의 인증 정보를 캡슐화합니다.
- SecurityContextHolder: 현재 보안 컨텍스트에 대한 액세스를 제공합니다.
- SecurityContext: 현재 인증된 사용자의 세부 정보를 보유합니다.
- SessionAuthenticationStrategy: 세션 관련 보안 정책을 적용합니다.
- RememberMeServices: "자동 로그인" 기능을 관리합니다.
- ApplicationEventPublisher: 인증 관련 이벤트를 시스템의 다른 부분에 알립니다.
- AuthenticationSuccessHandler: 인증 성공 후의 로직을 처리합니다.
이 과정은 Spring Security의 유연성을 보여주며, 각 단계를 필요에 따라 커스터마이즈할 수 있습니다.
HTTP Basic 인증
• HTTP 는 액세스 제어와 인증을 위한 프레임워크를 제공하며 가장 일반적인 인증 방식은 "Basic" 인증 방식이다
• RFC 7235 표준이며 인증 프로토콜은 HTTP 인증 헤더에 기술되어 있다
1. 클라이언트는 인증정보 없이 서버로 접속을 시도한다
2. 서버가 클라이언트에게 인증요구를 보낼 때 401 Unauthorized 응답과 함께 WWW-Authenticate 헤더를 기술해서 realm(보안영역) 과 Basic 인증방법을 보냄
3. 클라이언트가 서버로 접속할 때 Base64 로 username 과 password 를 인코딩하고 Authorization 헤더에 담아서 요청함
4. 성공적으로 완료되면 정상적인 상태 코드를 반환한다
Basic 인증 방법
Basic 인증은 HTTP에서 사용되는 가장 간단한 인증 방식 중 하나입니다.
이 방식의 작동 원리는 다음과 같습니다:
a. 사용자 이름과 비밀번호를 콜론(:)으로 결합합니다.
예: "username:password"
b. 이 문자열을 Base64로 인코딩합니다.
c. 인코딩된 문자열을 Authorization 헤더에 "Basic " 접두사와 함께 추가합니다.
예를 들어, Authorization 헤더는 다음과 같이 보일 수 있습니다
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
Realm (보안 영역)
Realm은 보호되는 리소스의 범위를 나타내는 문자열입니다.
이는 사용자에게 어떤 영역에 대한 인증을 요구하고 있는지 알려주는 역할을 합니다.
예를 들어, "관리자 영역" 또는 "사용자 프로필"과 같이 지정될 수 있습니다.
클라이언트는 이 realm 정보를 보고 어떤 자격 증명을 사용해야 할지 결정할 수 있습니다.
httpBasic() API
• HttpBasicConfigurer 설정 클래스를 통해 여러 API 들을 설정할 수 있다
• 내부적으로 BasicAuthenticationFilter 가 생성되어 기본 인증 방식의 인증 처리를 담당하게 된다
@EnableWebSecurity
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http, HttpSecurity httpSecurity) throws Exception{
http.authorizeHttpRequests(auth-> auth.anyRequest().authenticated())
.httpBasic(Customizer.withDefaults());
return http.build();
}
.formLogin()없애고 httpBasic()만 있다면
다음과 같은 프롬프트 창으로 로그인을 요청한다.
[claude]
HTTP Basic 인증은 가장 단순한 형태의 웹 인증 방식 중 하나입니다.
주요 특징:
- 간단한 구현: 사용자 이름과 비밀번호를 base64로 인코딩하여 HTTP 헤더에 포함시킵니다.
- stateless: 서버에 세션을 유지하지 않습니다.
- 모든 요청에 인증 정보 포함: 클라이언트는 매 요청마다 인증 정보를 보내야 합니다.
- 보안 취약점: HTTPS를 사용하지 않으면 중간자 공격에 취약할 수 있습니다.
formLogin() 없이 httpBasic()만 존재한다면 프롬프트창으로 로그인을 시킨다.
httpBasic()또한 없다면
- 기본 인증 메커니즘 없음: 특정한 인증 방식이 구성되지 않습니다.
- 접근 거부: 보호된 리소스에 접근하려고 하면, 기본적으로 403 Forbidden 오류가 발생합니다.
- 로그인 방법 부재: 사용자가 인증할 수 있는 표준 메커니즘(로그인 폼이나 HTTP Basic 인증)이 제공되지 않습니다.
- 보안 필터 체인: Spring Security의 다른 보안 필터들은 여전히 작동하지만, 사용자 인증을 처리할 특정 메커니즘이 없습니다.
httpBasic()또한 없다면 기본 인증방식또한 없으니 인증 받을 방법이 없다.
httpBasic() 추가 후 로그인 성공시
httpBasic() 추가 후 로그인 실패시
앞에 Basic은 Basic 인증방식을 의미한다.
[claude]
- WWW-Authenticate 헤더:
- 이는 HTTP 응답 헤더입니다.
- 서버가 클라이언트에게 인증이 필요하다는 것을 알리는 데 사용됩니다.
- 주로 401 Unauthorized 응답과 함께 전송됩니다.
- 이 헤더는 클라이언트에게 어떤 인증 방식을 사용해야 하는지 알려줍니다.
- Basic realm:
- WWW-Authenticate 헤더의 값으로 사용됩니다.
- "Basic"은 HTTP Basic 인증 방식을 나타냅니다.
- "realm"은 보호 영역을 식별하는 문자열입니다.
예시:
WWW-Authenticate: Basic realm="My Secure Site"
이 헤더의 의미:
- 서버가 HTTP Basic 인증을 요구하고 있음
- 보호 영역의 이름은 "My Secure Site"
realm의 역할:
- 사용자에게 표시: 많은 브라우저에서 인증 프롬프트에 이 realm 문자열을 표시합니다.
- 인증 범위 구분: 다른 realm은 별도의 인증을 요구할 수 있습니다.
- 비밀번호 관리: 브라우저가 realm별로 다른 비밀번호를 저장할 수 있게 합니다.
AuthenticationEntryPoint 만들어보기
@EnableWebSecurity
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http, HttpSecurity httpSecurity) throws Exception{
http.authorizeHttpRequests(auth-> auth.anyRequest().authenticated())
.httpBasic(basic -> basic.authenticationEntryPoint(new CustomAuthenticationEntryPoint()));
return http.build();
}
- AuthenticationEntryPoint 주요 목적:
- 인증되지 않은 사용자가 보안이 설정된 리소스에 접근하려고 할 때 어떻게 반응할지를 결정합니다.
- AuthenticationEntryPoint 핵심 기능:
- 인증 예외가 발생했을 때 클라이언트에게 적절한 응답을 보내는 역할을 합니다.
- 주로 401 (Unauthorized) 응답을 생성하고, 클라이언트에게 인증 방법을 알려줍니다.
- 인터페이스 정의:
public interface AuthenticationEntryPoint {
void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException;
}
- 사용 예시:
- 기본 로그인 페이지로 리다이렉트
- WWW-Authenticate 헤더를 포함한 401 응답 반환
- JSON 형식의 오류 메시지 반환 (RESTful API의 경우)
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
response.setHeader("WWW-Authenticate", "Basic realm=security");
response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase());
}
}
WWW-Authenticate 헤더가 있어야 인증을 시도한다.
[claude]
- 이 헤더는 서버가 클라이언트에게 인증이 필요하다는 것을 알리는 데 사용됩니다.
- 주로 401 Unauthorized 응답과 함께 전송됩니다.
- HTTP 표준에 따르면, 서버는 인증이 필요한 경우 WWW-Authenticate 헤더를 포함해야 합니다.
- 이는 클라이언트에게 명확한 지침을 제공하고 상호운용성을 보장하기 위함입니다.
WWW-Authenticate 헤더가 반드시 있어야만 인증을 시도할 수 있는 것은 아닙니다. 그러나 이 헤더는 클라이언트에게 필요한 인증 방식에 대한 중요한 정보를 제공하며, 표준화된 방식으로 인증 요구사항을 전달합니다. 헤더가 없는 경우에도 인증은 가능하지만, 클라이언트가 적절한 인증 방식을 추측해야 할 수 있으며, 이는 잠재적으로 문제를 일으킬 수 있습니다.
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
response.setHeader("WW-Authenticate", "Basic realm=security");
response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase());
}
}
이런식으로 헤더명을 바꾸면 로그인 프롬프트가 보이지않고 401 에러만 발생한다.
AuthenticationEntryPoint 인터페이스는 인증되지 않은 사용자가 인증이 필요한 요청 엔드포인트로 접근하려 할 때,
예외를 핸들링 할 수 있도록 하는것인데 그떄
response.setHeader("WWW-Authenticate", "Basic realm=security");
로 응답 헤더값을 채움으로서 클라이언트가 basic 인증방식이고 realm이 security이라는것을 알게한다.
또한
response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase());
응답 코드와 응답메시지를 통해 인증되지않은 사용자의 접근이라는것을 알린다.
[claude]
HTTP Basic Authentication 프로세스는 다음과 같이 진행됩니다:
- 초기 요청:
- 인증되지 않은 클라이언트가 보호된 리소스에 접근을 시도합니다.
- 서버 응답:
- 서버는 401 Unauthorized 상태 코드와 함께 'WWW-Authenticate' 헤더를 포함한 응답을 보냅니다.
- 예: WWW-Authenticate: Basic realm="security"
- 브라우저 동작:
- 브라우저는 'WWW-Authenticate' 헤더를 인식하고, 이에 대응하여 로그인 프롬프트를 표시합니다.
- 이 프롬프트는 브라우저에 내장된 기능으로, 운영체제나 브라우저 종류에 따라 모양이 다를 수 있습니다.
- 사용자 입력:
- 사용자는 프롬프트에 username과 password를 입력합니다.
- 재요청:
- 브라우저는 사용자가 입력한 정보를 Base64로 인코딩하여 'Authorization' 헤더에 포함시켜 서버에 재요청을 보냅니다.
- 예: Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
- 인증 처리:
- 서버는 'Authorization' 헤더를 디코딩하여 인증을 수행합니다.
- 인증이 성공하면 요청한 리소스에 대한 접근을 허용합니다.
댓글