読者です 読者をやめる 読者になる 読者になる

iOSでのVPN接続をちょっと調べてみる

http://www.infraexpert.com/study/dot1xz01.html

EAP方式のEAP-TLSなどでは相互に証明書が提出され信頼チェーンを確立する
※EAPの信頼のある証明書が必要

VPN関連の用語解説

  • IEEE802.1X(EAP-TLS) :有線LANや無線LANにおけるユーザ認証の規格
    • サプリカント :IEEE802.1Xにおけるクライアント(PCには標準搭載)
      • 無線ではEAPOLパケットで送信
    • 認証装置 :サプリカントと認証サーバの仲介役となるネットワーク機器
      • 結果に応じてアクセス制御をする
      • EEE802.1X対応のLANスイッチまたは無線LANアクセスポイント
      • 無線/有線でRadiusパケットを送信
    • 認証サーバ :ユーザ認証を行うサーバ
  • Radiusによる認証 :
    • 構成

資料系

iOSでFirebaseのGoogle認証登録を実装

f:id:surume_Reflection:20170520175010p:plain

記事

※注意※
17/05/20にFirebase4.0.0がリリースされていますが
過去バージョン指定をしないと動作しません



記事を書いている人間は、現段階でiOSアプリ開発の経験は2週間ほどで
基本Firebaseのガイド通りに実装しているだけなので 参考にはならないです
環境や注意点は書いてますが、メモレベルの記述なのであしからず..

環境:

開発環境-バージョン

xcode 8.3.2
cocoapod 1.2.1
Apple Swift 3.1
動作確認 (iOS 10.3)

SDK-バージョン

Firebase 3.17.0
GoogleSignIn 4.0.2

下準備:

xcodeのインストール (省略)
Firebaseにアカウント登録 (省略)
プロジェクトの作成
  1. iOSSingleViewApplicationを選択
    f:id:surume_Reflection:20170520160404p:plain

  2. アプリ名を入力後NEXTを押すと自動で生成されます。
    f:id:surume_Reflection:20170520160821p:plain

  3. Firebase側のAuthenticationのログイン方法から有効化
    f:id:surume_Reflection:20170520205539p:plain


1. ライブラリと初期設定:

cocoapodのインストー

$ gem install cocoapods
$ pod init # 管理ファイルを生成
$ vi Podfile # SDKの追記

※Podfileへの追記内容 f:id:surume_Reflection:20170520161028p:plain

  pod 'Firebase', '3.17.0'
  pod 'Firebase/Core'
  pod 'Firebase/Auth'
  pod 'GoogleSignIn', '4.0.2'

Firebaseにアプリを追加

  1. FirebaseのダッシュボードHOMEから概要のiOSを選択
  2. iOSバンドルIDに上記のBandleIdentfierの欄の内容をコピーペースト
    f:id:surume_Reflection:20170520162334p:plain ※BandleIdentfierはツリーの青いアプリ名ファイル選択してGeneralタブにあります。
  3. 設定ファイルのダウンロード設置
    f:id:surume_Reflection:20170520163419p:plain

アプリにREVERSED_CLIENT_IDを設定

  • 先ほど入れたGoogleService-info.plistREVERSED_CLIENT_IDをコピー f:id:surume_Reflection:20170520171658p:plain


  • プロジェクトのinfoURL Typeを追加し、URL Schemesにペースト f:id:surume_Reflection:20170520173140p:plain

2. 実装

インポートの記述

  1. AppDelegate.swiftViewController.swiftに下記を記述
import Firebase
import GoogleSignIn
  1. AppDelegate.swiftに初期化処理を記述 アプリ起動時のapplication:didFinishLaunchingWithOptions:内に記述します。
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch.
        FIRApp.configure()
        return true
    }

注意:
importでエラーが出ている場合はFramework Search Pathsがマッチしていない場合があります。
「CocoaPodsを使用しているプロジェクトでは、「.xcodeproj」のファイルから開くとビルドできません。」

コードの追記

AppDelegate.swift

import UIKit
import Firebase
import GoogleSignIn

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, GIDSignInDelegate, GIDSignInUIDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch.
        FIRApp.configure()
        
        GIDSignIn.sharedInstance().clientID = FIRApp.defaultApp()?.options.clientID
        GIDSignIn.sharedInstance().delegate = self
        
        return true
    }
    @available(iOS 9.0, *)
    func application(_ application: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any])
        -> Bool {
            return GIDSignIn.sharedInstance().handle(url,
                                                        sourceApplication:options[UIApplicationOpenURLOptionsKey.sourceApplication] as? String,
                                                        annotation: [:])
    }
    func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
        return GIDSignIn.sharedInstance().handle(url,
                                                    sourceApplication: sourceApplication,
                                                    annotation: annotation)
    }
    func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error?) {
        if error != nil {
            return
        }
        
        guard let authentication = user.authentication else { return }
        let credential = FIRGoogleAuthProvider.credential(withIDToken: authentication.idToken,
                                                          accessToken: authentication.accessToken)
        FIRAuth.auth()?.signIn(with: credential) { (user, error) in
            if error != nil {
                return
            }
        }
    }
    func sign(_ signIn: GIDSignIn!, didDisconnectWith user:GIDGoogleUser!, withError error: Error!) {
        print("ログイン認証成功");
    }

    func applicationWillResignActive(_ application: UIApplication) {}
    func applicationDidEnterBackground(_ application: UIApplication) {}
    func applicationWillEnterForeground(_ application: UIApplication) {}
    func applicationDidBecomeActive(_ application: UIApplication) {}
    func applicationWillTerminate(_ application: UIApplication) {}
}

ViewController.swift

import UIKit
import Firebase
import GoogleSignIn

class ViewController: UIViewController, GIDSignInDelegate, GIDSignInUIDelegate {

    override func viewDidLoad() {
        super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib.
        
        GIDSignIn.sharedInstance().uiDelegate = self
        GIDSignIn.sharedInstance().signIn()
    }
    func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error?) {}
    func sign(_ signIn: GIDSignIn!, didDisconnectWith user:GIDGoogleUser!, withError error: Error!) {}

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

NodeJSのWebSocketで入力内容の送受信

コマンド

$ npm init
$ npm i websocket
$ node server.js #サーバー動かす

コード

server.js
var http = require('http');
var WSServer = require('websocket').server;
var url = require('url');
var clientHtml = require('fs').readFileSync('test.html');

var plainHttpServer = http.createServer(function(req, res) {
    res.writeHead(200, { 'Content-Type': 'text/html'});
    res.end(clientHtml);
}).listen(8888);

var webSocketServer = new WSServer({httpServer: plainHttpServer});
var accept = ['localhost', '127.0.0.1'];

webSocketServer.on('request', function (req) {
    req.origin = req.origin || '*';
    if (accept.indexOf(url.parse(req.origin).hostname) === -1) {
        req.reject();
        console.log(req.origin + ' access not allowed.');
        return;
    }

    var connection = req.accept(null, req.origin);
    console.log((new Date()) + ' Connection accepted.');

    connection.on('message', function(message) {
            //if(msg.utf8Data === 'Hello'){}
            console.log('Received Message: ' + message.utf8Data);
            connection.sendUTF("<Echo>"+message.utf8Data);
            //websocket.send('sended from WebSocket Server');
    });

    connection.on('close', function (code,desc) {
        console.log('connection released! :' + code + ' - ' + desc);
    });
});
test.html
<html>
<head>
   <title>タイトル</title>
   <meta charset="utf-8">
</head>
<body>

<script>
var ws = new WebSocket("ws://localhost:8888");
ws.onmessage = function(e) {
   console.log("OnMessage:"+e.data);
};
ws.onclose = function (e) {
   console.log(e.code+"/"+e.type);
};

//1秒ごとに入力内容を送る
function sendData(){
   ws.send( document.getElementById('message').value );
}
setInterval(sendData, 1000);
</script>

<input id="message" type="text" value="フロント送信データ" />
<button onClick="sendData()">送信</button>

</body>
</html>

pureなnodejsでhtml表示とmysql接続

サーバー接続

一緒に見たいのでメモレベル削除予定 ※test.htmlを同階層に設置

const http = require('http');
const hostname = '127.0.0.1';
const port = 3000;

var server = http.createServer();
server.on('request', doRequest);

// ファイルモジュールを読み込む
var fs = require('fs');

// リクエストの処理
function doRequest(req, res) {
    
    // ファイルを読み込んだら、コールバック関数を実行する。
    fs.readFile('./test.html', 'utf-8' , doReard );
    
    // コンテンツを表示する。
    function doReard(err, data) {
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.write(data);
        res.end();
    }
    
}

MySQL接続と操作

他のサイトを参考にswitchで切り替えれるようにしただけ…
node init.js create_database #node_mysql_testデータベース作成
node init.js create_table #userテーブル作成
node init.js create_date ユーザー名 #ユーザー追加

const mysql = require('mysql');
const db_name = 'node_mysql_test';
const table_name = 'user';

var client = mysql.createConnection({
  host     : 'localhost',
  user     : 'root',
  password : ''
});

// 各種DB操作
console.log(process.argv);
switch(process.argv[2]){
    case "create_database":
        client.query('CREATE DATABASE '+ db_name, function(err) {
          if (err && err.number != mysql.ERROR_DB_CREATE_EXISTS) {
            throw err;
          }
        });
    break;
    case "create_table":
        client.query('USE '+ db_name);
        client.query(
            'CREATE TABLE '+ table_name+
            '(id INT(10) AUTO_INCREMENT,'+
            'name VARCHAR(100),'+
            'PRIMARY KEY (id))'
        ,function(err){
            console.log(err);
        });
    break;
    case "create_data":
        client.query('USE '+ db_name);
        client.query(
            'INSERT INTO '+ table_name+
            ' SET name = ?',
            process.argv[3], function(err, info) { console.log(err); });
    break;
    default:
        console.log("該当引数なし:"+process.argv[2]);
}


client.end();

10分でwebプログラミング初心者

f:id:surume_Reflection:20170417010823p:plain

プログラミングの難しい点は環境作りにある

初心者が最初につまづくであろう物がプログラミング環境の準備だ
バージョンがOSが前提ライブラリがモジュールが…

人間が紙に命令や手続きを書いて実行するのをプログラムと呼ぶのであれば
純粋なプログラミングに本来環境は必要ないと言える プログラム - Wikipedia



PCブラウザで見ているのであれば環境も必要ない

ブラウザのURL欄に以下を記述する事で実行できる
簡単だからぜひ手書きで実行してみてほしい

javascript:alert(“HelloWorld!!”);

javascript:までを手書きで書いて、実行部分のalert("HelloWorld!!");を書く
JavaScript疑似プロトコルと呼ばれる物でブックマークレットなどを作れる。


サンプル:こんにちわ世界

www.lifehacker.jp

※ブックマークのURL欄に記入



開発者ツール!!

F12を押してコンソール欄に
alert("HelloWorld!!");を入力Enter

開発者ツールって名前、プログラミングしてる感がありますねw
なんとここでプログラム言語のJavaScriptが使えます。
ブックマークレットjavascript:を抜かせばここから実行可能です。
f:id:surume_Reflection:20170417002745p:plain
ブラウザ時計表示サンプル:

(function(){function displayClock(){var nowDate = new Date();var h = nowDate.getHours();var m = nowDate.getMinutes();var s = nowDate.getSeconds();var textDate = right('0'+h,2)+':'+right('0'+m,2)+':'+right('0'+s,2);document.getElementById('divzumeclock').innerHTML = textDate;};function right(str,n){return str.split('').reverse().slice(0,n).reverse().join('');};window.scroll(0,0);if(document.getElementById('divzumeclock')){document.getElementById('divzumeclock').style.display = 'block';document.getElementById('divzumeclose').style.display = 'block';return;}var clk = document.createElement('div');if(document.all){var width = document.body.clientWidth;}else{var width = '100%';}clk.style.width = width;clk.style.height = '100%';clk.setAttribute('id','divzumeclock');document.body.insertBefore(clk,document.body.firstChild);clk.style.fontSize = '120px';clk.style.padding = '100px 0px 0px 0px';clk.style.textAlign = 'center';clk.style.opacity = 0.8;clk.style.filter = 'alpha(opacity=80)';clk.style.zIndex = 998;clk.style.backgroundColor = 'white';clk.style.position = 'absolute';clk.style.left = 0;clk.style.top = 0;var cls = document.createElement('div');if(document.all){cls.innerHTML = '<a href=\'\'>X</a>';}else{cls.innerHTML = '<a href=\'\'>X</a> ';}if(cls.attachEvent){cls.attachEvent('onclick',function(){document.getElementById('divzumeclose').style.display='none';document.getElementById('divzumeclock').style.display='none';return false;});}else{cls.addEventListener('click',function(event){document.getElementById('divzumeclose').style.display='none';document.getElementById('divzumeclock').style.display='none';event.preventDefault();},false);}cls.style.width = width;cls.style.height = '50px';cls.setAttribute('id','divzumeclose');document.body.insertBefore(cls,document.body.firstChild);cls.style.fontSize = '30px';cls.style.textAlign = 'right';cls.style.zIndex = 999;cls.style.position = 'absolute';cls.style.left = 0;cls.style.top = 0;setInterval(displayClock,250);})();



実際に開発していく

プログラミングは基本、複雑な物を除けば分岐繰り返しのみです


情報爆発が広告界で問題になってそうですが
こういった学習サイトが多く点在しています。
ドットインストールがシンプルでおすすめです。

www.sejuku.net

cod:iwの時間を操る装置!?

#どこかで見た事あると思ったら…

CODIWのコーリングカードの中に手に変な装置をつけているカードが


f:id:surume_Reflection:20170408125431j:plain



シンギュラリティー

f:id:surume_Reflection:20170408125610j:plain

www.youtube.com



プロトタイプ

f:id:surume_Reflection:20170408125733j:plain

www.youtube.com

Banished失敗例-理想だけで現場は成り立たない

はじめは難易度Mediamでbanished達がここに村を作ろうとしていた。
そこに突然指揮をとりはじめるプレイヤーが現われる。

banish達は先見を持ち未来を見越しているプレイヤーの指示通りにしていた。

生成された環境

川が遠い山にかこまれた地形

f:id:surume_Reflection:20170408094227j:plain




村壊滅までのフェーズ

1.まずはともあれ家が無いと困るので家を作成

2.横にトンネルを作れば将来有益になるため建造開始

3.食料が無いので釣り小屋山菜採りの小屋を建造開始

4.ここで石が無くなり周囲に石が無いので遠くから調達

ここで指揮者は気づくべきだった…

5.釣り小屋山菜採りの小屋が建ったものの飢えで半分以上死亡

f:id:surume_Reflection:20170408095909j:plain

6.時間経過を早め食料と人口が増えるのを待つ

7.冬が来るが人口が足りたいため石切り場を建造

8.そしてだれもいなくなった…

f:id:surume_Reflection:20170408101536j:plain




原因と結果

原因1:トンネル

原因として大きいのがトンネルの作成だそれにより資材となる石が不足
遠くへの調達が必要になった事で食料の調達が遅れた
トンネルの建造には大量の石が必要になる。

f:id:surume_Reflection:20170408100521p:plain

原因2:冬

Banishedでは冬は最初の関門である基本的に木材調達と薪割り場があれば問題ない
私は学習力がないので久しぶりにやるたびに冬で村が壊滅している

最後に…
理想を出す側現場を指揮する側は別にするべきだ
理想で現場は回らないぞと言う事