달력

12

« 2024/12 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
반응형

최근 회사에서 MSA를 도입하면서 keycloak을 처음 사용하게 되었다.

검색해보면 java에서 keycloak을 사용하는 법은 여러 가지로 많이 나오지만 

ionic에서 keycloak을 사용하는 법은 쓸데없이 플러그인을 사용해서 하라고 한다.

나도 처음엔 플러그인으로 해보려 했지만(플러그인으로는 실패하였다) 그보다 간단히 되는 방법을 찾았다.

원래 java 소스였는데 그냥 http 통신하는 거라 ionic에도 쉽게 적용되었다.

 

이건 ionic-angular http만으로도 작동되지만, 혹시 필요한 사람을 위해 ionic-native http 버전도 함께 공유한다.

import { Component } from '@angular/core';
import { Platform } from 'ionic-angular';
import { Http, RequestOptions, Headers } from '@angular/http';
import { HTTP } from '@ionic-native/http';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
  keycloakConfig = {
        url: 'https://your_keycloak_url/auth',
        realm: 'your_realm',
        client_id: 'your_client_id',
        client_secret : 'your_client_secret'
    };
    
  constructor(public http: Http,
                public n_http: HTTP,
                public platform: Platform) {
                
    this.getToken({email : "email@email.com"
                   pswd : "password!"}).then(res => {
      console.log(res);
    }).catch(error => {
      console.log("Error", error);
    });
  }

  getToken(userData) {
    if (this.platform.is('cordova') == false){ 
      return new Promise((resolve, reject) => {
        var body = "grant_type=" + "password"+
                   "&client_id=" + this.keycloakConfig.client_id +
                   "&username=" + userData.email +
                   "&password=" + userData.pswd +
                   "&client_secret=" + this.keycloakConfig.client_secret;
        var headers = new Headers();
        headers.append('content-type','application/x-www-form-urlencoded');
        let options = new RequestOptions({ headers:headers });
                
        this.http.post(this.keycloakConfig.url+'/realms/'+this.keycloakConfig.realm+'/protocol/openid-connect/token', body, options).timeout(5000).subscribe(res => {
            resolve(res.json());
          }, (err) => {
            reject(err);
          });  
        });
    } else {
      return new Promise((resolve, reject) => {
        var body = {grant_type: "password",
                    client_id: this.keycloakConfig.client_id,
                    username: userData.email,
                    password: userData.pswd,
                    client_secret: this.keycloakConfig.client_secret};
        this.n_http.setSSLCertMode('nocheck');
        this.n_http.setRequestTimeout(5);
        this.n_http.setHeader('*', 'content-type', 'application/x-www-form-urlencoded');
        this.n_http.post(this.keycloakConfig.url+'/realms/'+this.keycloakConfig.realm+'/protocol/openid-connect/token', body, {}).then(res =>{
            resolve(JSON.parse(res.data));
          }).catch(err =>{
            reject(err);
          });
        });
      }
    }
  }
}

 

이런 식으로 body만 아래 코드로 변경하여 토큰 리프레시도 가능하다.

var body = "grant_type=" + "refresh_token"+
           "&client_id=" + this.keycloakConfig.client_id +
           "&refresh_token=" + "your_refresh_token" +
           "&client_secret=" + this.keycloakConfig.client_secret;

 

 

 

*참고 Java source

String uri = "http://localhost:7080/auth/realms/{RealmName}/protocol/openid-connect/token";

HttpClient client = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(uri);
post.setHeader("User-Agent",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36");
List<BasicNameValuePair> urlParameters = new ArrayList<BasicNameValuePair>();
urlParameters.add(new BasicNameValuePair("grant_type", "password"));
urlParameters.add(new BasicNameValuePair("client_id", {ClientName}));
urlParameters.add(new BasicNameValuePair("username", {UserName}));
urlParameters.add(new BasicNameValuePair("password", {Password}));
post.setEntity(new UrlEncodedFormEntity(urlParameters));
HttpResponse response = client.execute(post);
System.out.println("Response Code : " + response.getStatusLine().getStatusCode());
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer result = new StringBuffer();
String line1 = "";
while ((line1 = rd.readLine()) != null) {
	result.append(line1);
}
System.out.println(result);

 

출처 : https://stackoverflow.com/questions/39356300/avoid-keycloak-default-login-page-and-use-project-login-page

반응형
:
Posted by 리샤씨
반응형

2019/07/24 - [개발/ionic2, Angular] - ionic에서 모바일 접근성 적용하기 (1) : toast

 

ionic에서 모바일 접근성 적용하기 (1) : toast

최근 ionic앱에 모바일 접근성(Mobile Accessibility)을 적용할 일이 생겼다. ionic에는 크게 ionic-angular, ionic-native로 나뉘어 지는데 플러그인들이 많은데 toast도 그중 하나다. 나는 평소 ionic을 테스트..

risha-lee.tistory.com

↑위 글과 연결된 글입니다.

 

이전에 설명했던 ionic-angular http의 문제를 수정하는 법을 작성하겠다.

 

원인은 인증서 문제라면서 앱에 인증서를 고정하라는 답변을 발견하였다.

하지만 native 소스를 직접 건드리는 것은 좋은 방법이 아닌 것 같아 더 찾아본 결과, 

가장 효율적으로 보이는 https release error 수정하는 법은 다음과 같다.

(ionic-angular http를 이미 사용하고 있다고 가정하고 코드를 작성하였다)

 

2019/01/15 - [개발/ionic2, Angular] - Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response. error 해결법

그리고 위 포스팅에서 쓴 것과 달리 간혹 핸드폰에서도 CORS 오류가 나는 현상을 발견하였다.

이 문제도 아래 코드로 해결되는 것을 확인하였다. (디바이스에서 약간 디버깅이 어렵다는 것 말고는 여러모로 이득이다)

=> https://로 시작하는 URI를 제대로 동작시키지 못하는 이유는 서버에서 SSL을 제대로 적용 못해서였고 서버에서 제대로 적용해주면 ionic-angular http를 사용해도 apk를 release 했을 때 제대로 동작함을 확인했음

비슷한 이유로 CORS 오류도 서버 문제일 가능성이 높음

디버깅이 어려우므로 정말 서버를 수정할 수 없는 경우 이외엔 아래의 소스를 사용하지 않을 것 같음

그래도 필요한 경우가 생길 수도 있으니 소스는 삭제하지 아니함 (2020. 09. 03)

참고 : forum.ionicframework.com/t/ionic-native-http-ngx-v-s-angular-common-http-which-should-be-used-in-an-ionic4-app/169629/8

 

1. ionic-native http를 설치한다.

$ ionic cordova plugin add cordova-plugin-advanced-http
$ npm install --save @ionic-native/http

 

2. app.module.ts에서 ionic-native http providers에 넣는다.

import { HTTP } from '@ionic-native/http';

@NgModule({
   .....
providers: [
     .....
     HTTP
  ]
})

 

3. ts 파일을 수정한다.

import { Component } from '@angular/core';
import { Platform } from 'ionic-angular';
import { Http } from '@angular/http';
import { HTTP } from '@ionic-native/http';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
    url:string = "your_server_url";
    page_index: number = 1;
   
    constructor(public platform: Platform,
                public http: Http,
                public n_http: HTTP) {
      this.goGetNoti();
    }
    
    goGetNoti() {
        var param = "?page_index=" + this.page_index;
        this.getNoti(param).then(data => {
          console.log("getNoti", data);
          var _data:any = data;
                
          if (_data.isOk == 'Y') {
            // success
          } else {
            // server error
          }
        }).catch(error => {
            console.log("Error", error);
        });
    }
    
    public getNoti(param: string) {
       if (this.platform.is('cordova') == false){ 
            return new Promise((resolve, reject) => {
                this.http.get(url+'/v1/noti' + param).timeout(5000).subscribe(res => {
                    resolve(res.json());
                }, (err) => {
                    reject(err);
                });  
            });  
        } else {
            return new Promise((resolve, reject) => {
                this.n_http.setSSLCertMode('nocheck');
                this.n_http.setRequestTimeout(5);
                this.n_http.get(url+'/v1/noti' + param, {}, {}).then(res =>{
                    resolve(JSON.parse(res.data));
                }).catch(err =>{
                    reject(err);
                });
            });
        }
    }
}

(보통 getNoti와 같이 동작하는 함수는 다른 ts에 넣고 사용하기 때문에 getNoti와 goGetNoti로 분리하였다)

 

this.n_http.setSSLCertMode('nocheck'); 이 부분이 SSL 확인하지 않게 해주는 부분인듯하다.

찾아보았으나 아쉽게도 ionic-angular http에서는 ionic-native http처럼 SSL 확인을 하지 않아도 되는 기능이 없다.

그래서 앞으로 http onic-angular, ionic-native 분기 코딩은 계속될 거 같다.

 

보안 문제를 살짝 생각해봤는데 보통 서버도 같이 개발해서

이미 인증된 서버이므로 위와 같은 방법을 써도 문제는 없을 것 같다.

=> 위와 같은 이유로 취소선 추가

 

참고 : https://stackoverflow.com/questions/44833534/http-requests-fails-only-while-releasing-android-apk

https://forum.ionicframework.com/t/https-post-requests-not-working-in-release-build/154099/3

 

반응형
:
Posted by 리샤씨
반응형

최근 ionic앱에 모바일 접근성(Mobile Accessibility)을 적용할 일이 생겼다.

 

ionic에는 크게 ionic-angular, ionic-native로 나누어지는데 플러그인들이 많은데 toast도 그중 하나다.

나는 평소 ionic을 테스트할 때 초반엔 ionic serve 명령어를 이용하여 웹으로 보기 때문에

toast를 포함하여 대부분의 기능을 ionic-angular에서 제공하는 것으로 사용하고 있었다.

 

그러나 ionic-angular에서 제공하는 것은 웹에서도 사용 가능하다는 장점이 있지만

cordova를 이용하여 디바이스(Android, IOS)에 올렸을 때,

native가 기본적으로 제공해주는 기능을 못 사용하는 경우가 있다는 걸 최근에 절실히 깨닫고 있다.

(코드를 꽤 많이 고쳐야 하는 경우도 생긴다)

 

아무튼 ionic-angular toast도 모바일 접근성을 테스트할 때 알게 된 사실인데,

삼성 안드로이드 폰에서 Voice Assistant를 이용하여 들으면

ionic 앱에서 ionic-angular toast를 읽어주지 않는다는 치명적인 단점이 있었다.

 

그래서 좀 찾아보고 직접 적용하여 테스트해 본 결과,

ionic-angular, ionic-native를 모두 적용하여 platform.is('cordova')로 분기를 태워 코드를 작성하면

웹과 앱 모두 적절한 toast를 사용할 수 있다.

(ionic-native toast를 사용하면 삼성 안드로이드 폰에서 Voice Assistant를 이용하여 들었을 때,

안드로이드 native로 작성된 앱의 toast처럼 정말 잘 읽어준다..!)

 

또한, ionic-angular http를 사용하면 apk를 release 했을 때 https://로 시작하는 URI를 제대로 동작시키지 못하지만,

이것도 위와 같은 방법으로 하면 해결된다. (ionic-angular, ionic-native 분기 적용)

=> https://로 시작하는 URI를 제대로 동작시키지 못하는 이유는 서버에서 SSL을 제대로 적용 못해서였고 서버에서 제대로 적용해주면 ionic-angular http를 사용해도 apk를 release 했을 때 제대로 동작함을 확인했음 (2020. 09. 03)

 

본론으로 들어가 코드를 작성해본다면 다음과 같다.

 

1. ionic-native toast를 설치한다.

$ ionic cordova plugin add cordova-plugin-x-toast 
$ npm install @ionic-native/toast --save

 

2. app.module.ts에서 ionic-native toast를 providers에 넣는다.

import { Toast } from '@ionic-native/toast';

@NgModule({
   .....
providers: [
     .....
     Toast
  ]
})

 

3. ts 파일을 작성한다.

import { Component } from '@angular/core';
import { Platform, ToastController } from 'ionic-angular';
import { Toast } from '@ionic-native/toast';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
  constructor(public platform: Platform,
              public toastCtrl: ToastController,
              public toast: Toast) {
      if (this.platform.is('cordova') == false) {
        let toast = toastCtrl.create({
            message: "test~",
            duration: 3000,
            position: "middle",
            cssClass: "toast-default"
        });
        toast.present();
      } else {
        this.toast.show("test~", "3000", "center").subscribe(
          toast => {
            console.log(toast);
          }
        );
      }
    }
  }

 

웹에서 보는 ionic-angular toast / 앱에서 보는 ionic-native toast

그러나 후에 ios에서 테스트해보았는데 ios의 voice over 기능으로는 toast message를 읽어주지 않았다.

나중에 작성하겠지만 간단히 설명하자면 ios에서는 phonegap-plugin-mobile-accessibility plugin을 설치하고

(<any>window).MobileAccessibility.speak(msg);

위 코드를 이용하여 원하는 메시지를 읽어주면 된다.

 

↓자세한 내용은 아래 링크에 작성해놓았다.

2019/09/18 - [개발/ionic2, Angular] - ionic에서 Voice Over/Voice Assistant/Talk Back이 켜져 있을 때 원하는 문장을 읽어주는 법 (모바일 접근성)

반응형
:
Posted by 리샤씨


반응형
반응형