Python3.6でセキュアなトークンを用意する

 Webアプリで認証機能を自作実装するにはセキュアなトークンが欠かせない。欠かせないんだけどPythonでは標準ではないライブラリを使ってトークンを得ていたので不便だった。

 Python3.5以前では、StackOverFlowを参考にして下記のようにトークンを得ていた。
How do I generate a cryptographically secure alphanumeric string in Python?
from Crypto.Random import random


def generate_auth_token():
""" Generate a 32-char alnum string. 190 bits of entropy. """
alnum = ''.join(c for c in map(chr, range(256)) if c.isalnum())
return ''.join(random.choice(alnum) for _ in range(32))


 Python3.6にはsecretsというライブラリが入り、hexやバイナリなど各種でトークンを作成できる。便利そう。
secrets — Generate secure random numbers for managing secrets
comment: 0

JavaScriptで文字列フォーマット

 アドベントカレンダーやってみたけどネタを生み出す時間が平日はなかなかきつい。今日も短めに。

 進化のスピードが早いJavaScript。文字列表現に変数を埋め込む方法が以前までなかったのだが、ぼくが気づかぬうちに追加されていた。

 文字列をバックティック「`」で囲む。バックティックであってシングルクォートではない。バックティックであってBUCK-TICKではない。
バックティックで囲んだら他言語と同じように、文字列中で変数名を「${}」で囲う。

var s = "foo";

console.log(`${s} bar`);
comment: 0

Seleniumでブログ自動投稿

 以前にあるブログへの自動投稿システムがほしいという要望があって、それをSeleniumでやった。

 ログインのやり方などは使用例が見つかるので良かったが、WYSIWYGを使っているtextareaへの入力がちょっと手間取った。ふつうは要素を探してその内容として文字列を挿入とやっていたのだが、WYSIWYGのフォームを適用されているとどう文字列を入れればええのよと。Seleniumではキーボード入力もシミュレーションできるので、結局要素をクリックしてキーボードシミュレーションで文字列を流し込んだが。

 そういうわけであるブログで記事投稿をする、C#でSeleniumを使ったコード。やってみた感想として、Seleniumの使い道はテスト、動作確認なのでそこまで型に縛られる必要はないだろうから、Pythonとかスクリプト言語でやったほうが楽だったなというところ。

using System;

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium.Support.UI;

namespace PlaySelenium
{
class Program
{
private static FirefoxDriver driver;
private static LogWriter log = new LogWriter("Selenium Test Sample");

static void Main(string[] args)
{
var url = "http://*****";

driver = new FirefoxDriver();

// Go to the home page
driver.Navigate().GoToUrl(url);

driver.FindElement(By.Id("usr_name")).SendKeys("*****");
driver.FindElement(By.Id("usr_password")).SendKeys("******");
driver.FindElement(By.Name("Submit")).Click();

if (driver.Title.Contains("ログイン"))
{
driver.FindElement(By.Name("user_name")).SendKeys("******");
driver.FindElement(By.Name("password")).SendKeys("******");
driver.FindElement(By.Id("login_button")).Click();
}

driver.Navigate().GoToUrl("http://******");

driver.FindElement(By.Name("entry_title")).SendKeys("エントリータイトル");

// switch ckeditor to source mode
driver.FindElement(By.XPath("//label[@for='sourceMode']")).Click();

// wait...
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(2));

// click to activate HTML input form
driver.FindElement(By.ClassName("CodeMirror-code")).Click();

// keyboard input emulation
driver.Keyboard.SendKeys("<h1>わっしょい</h1>");

// submit form
driver.FindElement(By.Name("srvEntryInputForm")).Submit();


log.Close();
driver.Quit();
driver.Dispose();
}


private static void AssertEqual(string a, string b)
{
if (a == b)
{
return;
}
else
{
var output = $"Test failed!\n" +
$"Page Title: {driver.Title}\n" +
$"URL: {driver.Url}\n" +
$"'AssertEqual' failed: {a} != {b}";
Console.WriteLine(output);
log.Add(output);
log.Close();
driver.Dispose();
Environment.Exit(1);
}
}

private static void AssertEqual(bool a, bool b)
{
if (a == b)
{
return;
}
else
{
var output = $"Test failed!\n" +
$"Page Title: {driver.Title}\n" +
$"URL: {driver.Url}\n" +
$"'AssertEqual' failed: {a} != {b}";
Console.WriteLine(output);
log.Add(output);
log.Close();
driver.Dispose();
Environment.Exit(1);
}
}
}
}
comment: 0

ドラッグ可能なイメージを使ってtextareaにイメージタグをドラッグアンドドロップで書き込む

 ブログに画像を入れるとき、その画像のURLを調べてタグを手書きで入れている。わりとめんどうだ。なのでドラッグアンドドロップを利用して、アップロードされてる画像一覧からイメージをタグで入れられるものを作った。

JSFiddleでのデモ

<textarea name="Body" cols="60" rows="20" ondrop="drop(event, this)" ondragover="allowDrop(event)"></textarea>

<div id="images"></div>
<script>
function allowDrop(ev) {
ev.preventDefault();
}

function drag(ev) {
ev.dataTransfer.setData('text/html', ev.target.src);
}

function drop(ev, target) {
ev.preventDefault();
console.log(target.id, ev.target.id)

var data = ev.dataTransfer.getData("text/html");
//alert(data);
var imgTag = "<img class='img' src='" + data + "' />";
var p = target.selectionStart;
var text = target.value;
target.value = text.substr(0, p) + imgTag + text.substr(p);
}
</script>
comment: 0

ブラウザにOneDriveAPIのJSONを渡して画像を表示

 OneDriveのAPIを使うとJSONで任意の情報を取得できる。前回に任意のディレクトリの子アイテム一覧をJSONで取得したので、今回はブラウザでそのJSONを受け取って、JSONに含まれているURLから画像ファイルを表示する…というJavaScript。

(function () {

document.getElementById("imageButton").addEventListener("click", function () {
var xhr = new XMLHttpRequest();
xhr.open("get", "/Master/OneDrive/Get");
xhr.responseType = "json";
xhr.addEventListener("load", function () {
var obj = JSON.parse(xhr.response);
var values = obj["value"];
for (var v in values) {
(function () {
var img = new Image();
img.src = values[v]["@@content.downloadUrl"];
img.width = 250;
document.getElementById("images").appendChild(img);
})();
}
});
xhr.send();
});
})();
comment: 0