JavaScriptでランダムなパスワードを生成する

JavaScriptを使ったランダムなパスワード文字列を生成するサンプルコードです。

/// length 桁のパスワードを生成する
function createRandomPassword(length){
  var lc = "abcdefghijklmnopqrstuvwxyz"; 
  var sList = lc + lc.toUpperCase()+"0123456789_-"; // 小文字 + 大文字 + 数字 + 対応する記号
  var password = ""; 
  for (i = 0; i < length; i++)
      password += sList.charAt(Math.floor(Math.random() * sList.length));
  return password;
}

// 利用例
var passwordLength = 12; 
var myPassword = createRandomPassword(passwordLength);
console.log(myPassword);
prompt(passwordLength + "桁のパスワードを生成しました。", myPassword);

デモ:

桁数:

ボタンを押すたびランダムなパスワード文字列を作成します。
ポチポチ押してみてくださいね。

連番入力の自動化

– 自分ではよくやるけど、あまり見ないため、書き方をメモ。
– 言語共通の配列処理や、 Java の JDBC で使う PreparedStatement.setXxx() 等、パラメータで連番(1,2,3,4 …)にして複数同じ処理をする必要がたびたびある。
これをそのまま手入力すると、数が増えると手間で、入れ換えが面倒で、この煩雑さがミスも誘発する、ということもある。これを楽するには、変数を使ってインクリメントしていくとよい。たとえば次の通り:

foo(0, “abc”);
foo(1, “def”);
foo(2, “ghi”);
// :

というのを、

int i = 0;
foo(i++, “abc”);
foo(i++, “def”);
foo(i++, “ghi”);

とする。入れ換えも1文を差し替えるだけで済むし、制御文をはさんでも順序が崩れたりしないので便利。加算用の数値変数が残るのが気になるので自分ではスコープ区切って使ってます。

{
  int i = 0;
  foo(i++, “abc”);
  foo(i++, “def”);
  foo(i++, “ghi”);
}

途中で変数を宣言できない C でも、スコープを切ったバージョンは使える。

Tomcat 5.x で Servlet をマップできない

– web.xml で定義とマッピングをちゃんとしても、その URL でアクセスすると 500 エラーになって表示されず、*.war でやるとそのファイルだけデプロイされないという状態になっていた。

javax.servlet.ServletException: ラッパがサーブレットクラス com.example.my.FooServlet 又はそれが依存するクラスを見つけることができません

となって、

java.lang.ClassNotFoundException: com.example.my.FooServlet

が続く。
– 原因は一言では $TOMCAT_HOME/server/lib に servlet-api.jar が無かったこと($TOMCAT_HOME/common/lib にはあったがだめだった…何かが原因で親である common の設定がクリアされた?)。サンプルのサーブレットが動いてたかは確認してないが、とりあえずこんな感じで対処:

cp -p common/lib/server-api.jar server/lib/

– 参考:
http://jakarta.apache.org/tomcat/tomcat-5.0-doc/class-loader-howto.html
– The Apache Jakarta Tomcat 5 Servlet/JSP Container – Class Loader HOW-TO
http://www.atmarkit.co.jp/fjava/javatips/049jspservlet025.html
– @IT: Java TIPS — クラスローダの仕組みを知る

XML のデータ整合性をチェックする

– Visual Studio.NET の Microsoft Development Environment
– Eclipse
– Emacs – PSGML
OpenJade,OpenSP: それぞれ Jade, SP を DSSSL コミュニティが受け継いでメンテナンスと拡張をしているバージョン。元となった Jade/SP は既に配布されていない。
http://www.sscd.de/openjade/
– OpenJade Windows Binaries and Sources.

Firefox の Web 系開発者用プラグイン

http://chrispederick.com/work/firefox/webdeveloper/
– Web Developer Extension (Mozilla/Firefox plugin)
Documentation -> Features に機能一覧がある。Web 周りの言語の構文チェックが豊富。
– ちなみに国際化もされていて、そっちをいれれば日本語で使えるので安心。
 
– 難点:
— ローカルファイル検証(HTML/CSS のみ対応)のときも validator.w3c.org にデータを送信するため、公開するとまずい系には使うべきではないこと。

JSP 基本文法

– <% 〜 %> で囲んだ部分は全体で1つのメソッドのように Java コードが書ける.

<body>
  <%
    out.println(“Hello, world!”);
  %>
</body>

– <%= 〜 %> で囲んだ部分は一つの式として評価され、戻り値をその部分に表示する( つまり void は不可)。複文になってはならないため、セミコロンは用いない。

Your name is <%= name %>

– <%! 〜 %> で囲んだ部分はクラス内の定義とみなす

  <%!
    private static final int FOO = 1;
    private void final doSomething(String value){ /* do something */ }
  %>

– <%@ 〜 %> で囲んだ部分は JSP の制御タグとする

  <%@ page contextType="text/html; charset=EUC-JP" %>
  <%@ page import="java.sql.*" %>
  <%@ page import="java.util.*" %>

– JSP のインクルード構文:
— <jsp:include page=”foo.jsp” /> – 対象のページを 別に実行して, 結果を動的に(コンパイル後に)インクルードする。ローカル変数, request パラメータはファイルごとに独立になる。

view.jsp:
  <body>
    Hi, <jsp:include page=”inc.jsp”/>.
  </body>
 
inc.jsp:
  <%= "John" %>

— <%@ include file = "foo.jsp" %> – 対象のページをそのまま読み込み、静的に(コンパイル時に)インクルードする。ローカル変数は共存になり、インクルード対象(exp. inc.jsp)のファイルが更新されてもインクルード元(ex. foo.jsp)は再コンパイルされないため、全てのインクルード元について明示的に更新してやらなければならない。

view.jsp:
 <body>
   <%@ include file = "inc.jsp" %>
   Hi, <%= name %>.
 </body>
  
inc.jsp:
  <% String name = "John"; %>

– 参考:
http://www.javaroad.jp/servletjsp/index.html
– Java の道: Servlet, JSP

Java で MD5

java.security.MessageDigest を使うと簡単。

MessageDigest md;
try {
    md = MessageDigest.getInstance(“MD5”);
} catch(NoSuchAlgorithmException e) {
    e.printStackTrace();
    return;
}
// digest を求めるバイト列設定
// update(“Hello, world!”.getBytes()) と同じ。
md.update(“Hello, “.getBytes());
md.update(“world!”.getBytes());
// 計算して求めるがそのままだとバイト列なので文字列化.
final byte[] digest = md.digest();
final String sHexDigest; {
final StringBuffer buf = new StringBuffer(“”);
    for(int i=0; i < digest.length; i++){
        final int n = digest[i] & 0xFF;
        if(n < 16) buf.append("0");
        buf.append(Integer.toString(n, 16));
    }
    sHexDigest = buf.toString();
}
 
System.out.println(sHexDigest);

ネットワークにつながっているプロセスを調べる

– CUI では fport, GUI では ActivePorts というのがある。
http://www.foundstone.com/index.htm?subnav=resources/navigation.htm&subcontent=/resources/proddesc/fport.htm
– fport
http://www.ntutility.com/
– ActivePorts
http://www.atmarkit.co.jp/fsecurity/rensai/securitytips/003fport.html
– @IT:Security Tips – 自マシンの開きポートとプロセスの関係を確認する

JDB を使う

– 昨日の一件のおかげで初めて Java のデバッガを使うことに。
– デバッグ対象の JVM のオプションに

-Xdebug -Xrunjdwp:transport=dt_socket,address=50000,server=y,suspend=n

を追加して実行(Resin の場合は httpd.sh の args=”…” を -J-Xdebug -J-Xrunjdwp:…のように -J を付与)しておけば次のようなデバッグができる。

$ jdb -attach 50000

threads

グループ tcp-server:
  (java.lang.Thread)0x3b0 tcp-accept-8080 実行中
  (java.lang.Thread)0x3b1 tcp-accept-8080 状況待機中
  (java.lang.Thread)0x3b2 tcpConnection-8080-0 状況待機中

thread 0x3b2

tcpConnection-8080-0[1] suspend
すべてのスレッドが中断されました。
tcpConnection-8080-0[1] where
  [1] java.lang.Object.wait (ネイティブ メソッド)
  [2] com.caucho.server.TcpServer.accept (TcpServer.java:648)
  [3] com.caucho.server.TcpConnection.accept (TcpConnection.java:211)
  [4] com.caucho.server.TcpConnection.run (TcpConnection.java:132)
  [5] java.lang.Thread.run (Thread.java:534)
tcpConnection-8080-0[1] resume
すべてのスレッドが再開されました。

quit

という感じでかなり便利。
http://java.sun.com/j2se/1.4/ja/docs/ja/tooldocs/win32/jdb.html#description
– Sun JDK ドキュメント: jdb – Java デバッガ

JDBC のログとりメモ

– close() するのは PreparedStatement#close() でなく ResultSet#close() でもなく、絶対に Connection でなければならない。
– ログ情報には PreparedStatement#toString() がよさげ(少なくとも com.mysql.jdbc では)。
理由は、ログのための利便性から。SQLException がどのクエリでエラーになったかを残してくれないので、 PreparedStatement インスタンスがクエリ周りの情報をきっちり保持してくれていれば、toString() でログにどのクエリ文を実行したかが残せる。しかし、PreparedStatement#close() は DB 接続を閉じる仕様とは限らないため、Connection#close() を呼ぶ必要がある。PreparedStatement#close() だけにしたらプールがあふれ、思わぬ場所で DB 接続が開くのをずっと待ち続けることになってしまった。
– 例:

boolean isExist(int id){
    PreparedStatement ps = null;
    try{
        final Connection con = getConnection();
        try{
            ps = con.prepareStatement(“SELECT id FROM list WHERE id = ? LIMIT 1”);
            ps.setInt(1, id);
            return ps.executeQuery().next();
        }finally{
            con.close();
        }
    }catch(SQLException e){
        log(“Query error [“+ps+”]”, e); // void log(String, Throwable); とする
        return false;
    }
}