서버와 클라이언트 간의 인증을 HTTP 헤더를 통해 수행하는 방식으로, Http Basic, Http Digest, Oauth 와 같은 프로토콜을 통해 구현하는 것이 일반적이다. 그 외에는 특정 헤더에 토큰을 넣어 보내고 서버 측에서는 그 헤더값을 꺼내 사용자를 인식하고 인증한다.
클라이언트 쪽에서 따로 별도의 저장공간을 사용하는 네이티브, 즉 안드로이드나 IOS 쪽에서 많이 사용한다. 모바일은 따로 DB를 가지고 있는데, 특정 토큰이나 값을 저장하고 해당 애플리케이션에서만 접근이 가능하게 설정할 수 있다. 보안이 잘 되어있어 따로 유출된다거나 저장된 값을 뽑아오는 것도 거의 불가능에 가깝다.
반대로 웹은 브라우저에서 콘솔 혹은 자바스크립트로 현재 페이지의 변수와 변수의 값을 추출할 수 있다. 즉 보안이 취약하다.
그렇기 때문에 브라우저 방식을 지원하는 웹앱의 경우 쿠키를 사용하는 것이 일반적이며,
그 외의 네이티브 앱은 헤더 인증 방식도 많이 사용한다.
지난번에 작성했던 cookie 프로젝트에서 index.html의 ajax 함수를 수정해준다. dataType에서 데이터를 JSON으로 받게 설정하는 줄을 주석처리하고, 다음을 추가한다.
success: function(response){
console.log(response);
},
UserService에서 login 성공시 쿠키를 세팅하는 부분은 주석처리하고 유저의 ID를 반환하도록 수정한다. 다음에는 AccountApiController에서 /login이 String을 리턴하게 바꿔준다.
public String login(
LoginRequest loginRequest,
HttpServletResponse httpServletResponse
) {
var id = loginRequest.getId();
var pw = loginRequest.getPassword();
var optionalUser = repository.findByName(id);
if (optionalUser.isPresent()) {
var userDto = optionalUser.get();
if (userDto.getPassword().equals(pw)) {
return userDto.getId();
} else {
throw new RuntimeException("User not found");
}
}
return null;
}
// AccountApiController
@PostMapping("/login")
public String login(
@RequestBody LoginRequest loginRequest,
HttpServletResponse httpServletResponse
){
return service.login(loginRequest,httpServletResponse);
}
인증을 확인하기 위해서 UserApiController에는 /api/user/me2를 추가한다.
@GetMapping("/me2")
public UserDto me(
@RequestHeader(name="authorization", required = false)
String authorizationHeader
){
log.info("authorizationHeader: {}", authorizationHeader);
var optionalUserDto = repository.findById(authorizationHeader);
return optionalUserDto.get();
}
쿠키와 비슷하게, 로그인에 성공한 후 /api/user/me2로 접근할 경우 헤더에서 authorization라는 이름에 저장된 값을 가져와서 그 값을 로그에 찍어낸다. 또, 헤더에 저장된 값과(=랜덤 생성된 고유식별ID) 일치하는 ID를 가진 UserDto를 검색해 반환한다. 없을 경우에는 null을 반환한다.
그런데 이대로 실행해보면 콘솔에 로그인한 값이 제대로 찍히지만 /me2는 오류가 발생한다. NullPointerException가 발생하였는데, 이는 request header에 authorization이 저장되지 않았기 때문이다.
헤더에 값을 추가하려면 Talend API나 Postman을 사용한다.
header에 authorization을 추가하고, 로그인에 성공했을 때 콘솔에 출력되었던 ID를 복사하여 첨부한다.
제대로 header 값을 받아 UserDto를 반환한 것을 확인할 수 있다.
세션, 쿠키, 헤더를 통한 인증 방식을 살펴보았다. 결론적으로 모든 인증은 HTTP 헤더를 통해서 실행되는데, 이것이 관리되는 방식이나 보안의 강도에서 차이가 나게 된다. 결국 인증 정보들을 전달하는 방식은 쿠키이다. 쿠키의 특성에 따라 세션에서 관리되면 세션 인증이고, 클라이언트에서 관리되고 쿠키에 있는 값으로 인증하면 이것이 쿠키 인증이다. 별도로 헤더를 만들어서 토큰이나 아이디를 전달해 인증하는 것은 HTTP 헤더를 통한 인증이다.
+쿠키는 모바일 환경에서도 사용할 수 있지만, 직접 관리를 해주어야 하므로 자동으로 관리해주는 웹 브라우저에 좀 더 어울린다.