플러터에서 개인 서버와 https 통신중에 에러가 발생했다.
에러 내용을 보면 unable to get local isser certificate 라고 한다.
이 에러는 요청하는 서버의 인증서가 유효하지 않다는 것이다.
처음에는 인증서 자체가 잘못된 줄 알았다. 하지만 Postman으로 요청 보내면 문제 없이 잘 되더라...
스택오버플로우나 구글링을 해보면 아래와 같은 코드를 본 경우도 있을 것이다.
class MyHttpOverrides extends HttpOverrides{
@override
HttpClient createHttpClient(SecurityContext? context){
return super.createHttpClient(context)
..badCertificateCallback = (X509Certificate cert, String host, int port)=> true;
}
}
void main() {
HttpOverrides.global = MyHttpOverrides();
runApp(const MyApp());
}
개인적으로는 위와 같은 코드는 추천하지 않는다.
위 코드는 https 통신시에 모든 호스트에 대해 SSL 인증서 검증을 true로 넘기는 것이다.
즉, 보안 검증을 진행하지 않기 때문에 위험하다. (보안 때문에 ssl 쓰는 건데 이러면 무슨 소용...)
만약 외부 api와 통신하다가 이런 문제가 발생한다면 true를 리턴할 게 아니라 내가 요청을 보낼 도메인만 true를 반환하도록 해주자.
아래부터는 본인이 운영하는 개인 서버와 통신하다가 이러한 문제가 발생했을 때의 해결방법이다.
원인
nginx에서 사용하는 인증서가 cert.pem이라서 생긴 문제였다.
요즘 사용하는 대부분의 프레임워크에서는 https 통신할 때 서버의 인증서가 유효한지 확인하는것으로 끝나지 않는다.
인증서 체인을 통해 서버에 등록된 인증서가 루트인증서에 의해 발급되었는지 확인한다.
위 이미지를 보면 알겠지만 모든 인증서를 루트기관에서 발급하지는 않는다.
중간 인증 기관이 있는데, cert.pem은 내 서버만 인증해줄 뿐 중간기관에 대한 정보가 없다.
그렇기 때문에 클라이언트 입장에서는 해당 ssl 인증서가 루트기관에서 검증이 되는지 확인이 불가능하기 때문에 에러를 발생시킨 것이다.
해결방법
인증서 기관들의 정보를 담고 있는 chain.pem 파일이 있다.
인증서를 발급하면 cert.pem, privkey.pem과 같이 발급된다.
일반적으로 cert.pem과 chain.pem을 합친 fullchain.pem 파일도 같이 발급된다.
cert.pem 대신 fullchain.pem을 인증서로 사용하면 된다.
'프로그래밍 > 발생한 에러들' 카테고리의 다른 글
java.lang.NoClassDefFoundError: javax/persistence/Entity (0) | 2023.01.02 |
---|---|
[NestJS] SELECT시 DTO에 OmitType 적용 안되는 이슈 (0) | 2022.10.31 |
[jest] ReferenceError: React is not defined (0) | 2022.04.16 |
[Flutter / Android] Warning: Mapping new ns to old ns. This app is using a deprecated version of the Android embedding (4) | 2021.12.14 |
[Javascript] getElementById is not a function (0) | 2021.10.02 |