증상

Invalid barcode

The barcode [URL] is not a valid authentication token barcode
 

구글 Authentication 앱을 사용해서 MFA 시스템을 구축하였는데 안드로이드에선 잘 작동하지만 IOS 아이폰에선 작동하지 않는 현상이 발생하였다.

 

다요소 인증 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. RSA SecurID 토큰. 어디에도 연결되지 않은 토큰 생성기의 예. 다요소 인증(多要素認證, Multi-factor authentication, MFA)은 적어도 다음 분류 중 두 가지에 한해 별도의 여

ko.wikipedia.org

 

원인

구글 Authentication은 TOTP 를 구현하여 작동한다. 해당 알고리즘에서 키값을 암호화 하는데 BASE32 인코딩을 사용하였는데, 인코딩 된 결과값이 자리수를 맞추기 위해 더해지는 패딩문자 '='가 IOS에서 인식하지 못하여 발생하는 문제였다.

 

시간 기반 일회용 비밀번호 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 시간 기반 일회용 비밀번호(Time-based one-time password, TOTP)는 현재 시간을 고유성의 원천으로 사용하여 일회용 비밀번호 (OTP)를 생성하는 컴퓨터 알고리즘이다. HMAC

ko.wikipedia.org

 

해결책

처음에는 URL 인코딩을 처리하면 해결될 줄 알았는데, 여전히 같은 에러가 발생하였다.

테스트를 진행하다 보니 패딩된 문자 '='는 복호화시 제거하여도 같은 값을 돌려주는 무의미한 문자여서 제거하고 테스트하였더니 아이폰에서도 정상작동하였다.

증상

 

404 Not Found

Vue.js를 사용한 웹 애플리케이션 개발 중 새로고침 시 404 페이지로 리다이렉트 되는 이슈가 발생하였다.

 

원인

 

해당 이슈는 SPA 앱을 개발할 때 발생하는 이슈로 connect-history-api-fallback 현상이라 한다.

Vue.js의 경우 라우터에 등록된 Vue 컴퍼넌트들을 모듈 번들러를 통하여 Javascript로 컴파일하여 WebServer의 Document Root 폴더에 가지고 있다. 

라우터를 이용한 정상적인 페이지 요청 시에는 해당 페이지에 맞는 js 파일을 클라이언트가 요청하지만, 새로고침 시에는 도메인과 라우터 Path를 가지고 WebServer에 존재하지 않는 요청을 보내기 때문에 발생하는 이슈이다.

 

해결방법

라이브러리를 사용하는 방법도 있지만, 공식 문서에 나와있는 서버 설정방법을 사용하여 해결하였다.

https://router.vuejs.org/guide/essentials/history-mode.html

 

Different History modes | Vue Router

Different History modes The history option when creating the router instance allows us to choose among different history modes. Hash Mode The hash history mode is created with createWebHashHistory(): import { createRouter, createWebHashHistory } from 'vue-

router.vuejs.org

 

해당 방법은 WebServer에 Http 요청이 들어왔을 때, 해당 요청을 rewrite 하는 방법이다.

 

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.html [L]
</IfModule>

 

서버 설정 문법은 아파치 레퍼런스 문서를 참고하면 된다.

https://httpd.apache.org/docs/current/rewrite/flags.html

 

RewriteRule Flags - Apache HTTP Server Version 2.4

RewriteRule Flags This document discusses the flags which are available to the RewriteRule directive, providing detailed explanations and examples. A RewriteRule can have its behavior modified by one or more flags. Flags are included in square brackets at

httpd.apache.org

위 설정문을 예시로 번역하면

RewriteRule ^index\.html$ - [L]

^index\.html$ 는 정규표현식으로 

index로 시작하며(^ 접두사)  (특수문자 .) html 로 끝나지 않는($ 접미사) 요청들이 다시 쓰는 대상이며

[L] 플래그는 조건의 끝을 의미한다.

Rewirte Cond 문장의 ! -f, ! -d는 파일과 디렉토리를 의미한다.

 

결론적으로 SPA 애플리케이션의 초기진입 페이지인 index.html이 아닌 URL로 들어오는 요청들을 index.html로 다시 보내는 설정이다.

위와같은 설정을 웹서버에 적용하여, Vue.js의 새로고침 시 404 페이지 리다이렉트 이슈를 해결할 수 있다.

 

참고자료

 

https://stackoverflow.com/questions/36399319/vue-router-return-404-when-revisit-to-the-url

 

Vue Router return 404 when revisit to the url

I just enable Vue router history mode. And it work fine when I visit to vue routing via v-href or href. But, when I try to refresh that page or go directly from browser address bar, it just return ...

stackoverflow.com

 

 

증상

SQL 실행 시 파라미터 인덱스 관련 에러가 발생한다.

Caused by: java.sql.SQLException: Parameter index out of range (3 > number of parameters, which is 2).
```
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:963)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:896)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:885)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:860)
at com.mysql.jdbc.PreparedStatement.checkBounds(PreparedStatement.java:3321)
at com.mysql.jdbc.PreparedStatement.setInternal(PreparedStatement.java:3306)
at com.mysql.jdbc.PreparedStatement.setInternal(PreparedStatement.java:3345)
at com.mysql.jdbc.PreparedStatement.setNull(PreparedStatement.java:3384)
at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_setNull(FilterChainImpl.java:2733)
at com.alibaba.druid.filter.FilterAdapter.preparedStatement_setNull(FilterAdapter.java:1286)
at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_setNull(FilterChainImpl.java:2730)
at com.alibaba.druid.proxy.jdbc.PreparedStatementProxyImpl.setNull(PreparedStatementProxyImpl.java:397)
at com.alibaba.druid.pool.DruidPooledPreparedStatement.setNull(DruidPooledPreparedStatement.java:266)
at org.apache.ibatis.type.BaseTypeHandler.setParameter(BaseTypeHandler.java:39)
at org.apache.ibatis.executor.parameter.DefaultParameterHandler.setParameters(DefaultParameterHandler.java:91)
at org.apache.ibatis.executor.statement.PreparedStatementHandler.parameterize(PreparedStatementHandler.java:77)
at org.apache.ibatis.executor.statement.RoutingStatementHandler.parameterize(RoutingStatementHandler.java:58)
at org.apache.ibatis.executor.SimpleExecutor.prepareStatement(SimpleExecutor.java:71)
at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:56)
at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:267)
at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:141)
at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:105)
at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:81)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:101)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:95)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:355)
... 48 more

 

원인

mybatis의 sql 파일은 XML로 작성하는데, 흔히 사용하는 SQL의 주석처리 방법 --은 XML에서 사용하는 문법이 아니기 때문에 발생하였다.

 

해결방법

주석 처리를

<!-- 주석처리할 내용 --!>

문법을 사용하여 주석처리 하거나, 해당 내용을 삭제하면 해결할 수 있다.

+ Recent posts