最近

最近は忙しい。



そして、今日は応用情報技術者試験だった。



結果は多分駄目だろう。



10月こそは絶対とる。



とりあえず試験は終わったから、最近興味があるJavaScriptを勉強しなおす。



http://openlab.dino.co.jp/category/workshop/ws_javascript




DINOさんの勉強会の資料と内容はホント分かりやすい。

Subversionでバージョン管理したくないファイルの設定について

Subversionでバージョン管理したくないファイルが有る場合はsvn:ignore属性を追加します。

EclipseSubversiveプラグイン使ってsvn:ignore属性を追加してたのですが、どこにどういう設定ファイルができるとか仕組みがいまいちわからないまま使っていたので、ちょっと調べてみました。

Subversiveプラグイン

svn:ignore属性を追加する

1.Eclipseからバージョン管理したくないファイルを右クリックして、[team]->[Add to svn:ignore...]を選択します。
2.コミットします。

作成されるファイル

.svnディレクトリに dir-prop-base というファイルが作成されます。多分、[Add to svn:ignore...]を選択したときに作成されるファイルだと思います。ファイルを確認してみると。次のようになっています。

K 10
svn:ignore
V 57
target

.classpath

.tomcatplugin

.settings

repo

work

END

.settingディレクトリ、targetディレクトリ、repoディレクトリ、workディレクトリ、.classpathファイル、.tomcatpluginファイルにadd:ignore属性を追加したのでそのようにファイルが作成されています。

Subversiveプラグインで確認

1.svn:ignore属性の設定を確認したいディレクトリを右クリックして、[team]->[Show Properties]を選択します。
2.SVN PropertiesのViewが表示され、svn:ignoreというプロパティと値を確認することができます。

svn:ignore属性をはずす

1.SVN PropertiecのViewからsvn:ignoreプロパティを右クリックして[Edit...]を選択します。
2.はずしたいディレクトリ名、ファイル名をsvn:ignoreプロパティの値から消してコミットします。


SVNコマンド

svn:ignore属性を追加する

1.svn propedit svn:ignore [ディレクトリパス] コマンドでsvn:ignore属性を追加したいディレクトリ名、またはファイル名を入力します。
2.コミットします。

C:\repos>\1\svn-win32-1.5.4\bin\svn.exe propedit svn:ignore maven2
属性 'svn:ignore' の新しい値を 'maven2' に設定しました

*1

作成されるファイル

これはSubversiveプラグインのときと同じファイルができていました。

K 10
svn:ignore
V 1
tmp

END

svn:ignore属性をはずす

svn:ignore属性を追加する方法と同じではずすディレクトリ名、ファイル名を削除して、コミットします。



以上

*1:作業ディレクトリ[maven2]にsvn:ignore属性を追加した実行ログ

ハイフン(-)付のデータベース名を作成する

できないと思ってたら、できたので書いておく。

PostgreSQL 8.1.11

失敗

postgres=# CREATE DATABASE x-xxxdb;
ERROR: syntax error at or near "-" at character 18
LINE 1: create DATABASE x-xxxdb

成功

postgres=# create DATABASE "x-xxxdb";
CREATE DATABASE

ダブルクォート(")で囲めば良いみたいですね。


MySQLでは、バッククォート(`)で囲むみたいですね。
MySQLで"-"(ハイフン)を含むデータベース名を付けたい場合 - 元RX-7乗りの適当な日々

サーブレットの認証を使わずに@Executeのroles属性を有効に使う方法

SAStrutsで認証を実装したいのですが、お勧めはサーブレットの認証機能を使って認証する方法みたいです。


認証 - cypher256's blog


今回はアプリケーションサーバTomcatで、ユーザ情報はDBで管理したいのでJDBCRealmを使ってやろうかなと思っていました。

ところが、ログインの認証機能が複雑な仕様になってしまって、JDBCRealmでは実現できないことがわかりました。

何とか、@Executeのroles属性でメソッド単位に認証をかけたいと思って、調べました。

調査

そもそも、どのようにrolse属性に設定したロールで認証がかかっているのか?

また、会社にあったStruts in アクションに書いてあるんじゃないかと思って、ActionMappingのrolse属性を見てみました。

以下、抜粋。

セキュリティチェックは、RequestProcessorのprocessRoles()メソッドで処理されます。RequestProcessorをサブクラス化することにより、アプリケーションベースのセキュリティでもrolesプロパティを使用できます。

何かできそうだ!!

さらに、RequestProcessor#processRoles()を見てみると…。

String roles[] = mapping.getRoleNames();
if ((roles == null) || (roles.length < 1)) {
    return (true);
}

// Check the current user against the list of required roles
for (int i = 0; i < roles.length; i++) {
    if (request.isUserInRole(roles[i])) {
        if (log.isDebugEnabled()) {
            log.debug(" User '" + request.getRemoteUser() +
                "' has role '" + roles[i] + "', granting access");
        }
        return (true);
    }
}

mapping.getRoleNames()でロール属性を取得して、request.isUserInRole()で検証している。


ということは…。


isUserInRole()メソッドをオーバーライドすればできる!?

実装

サーブレット仕様の認証を使わずにgetRemoteUserやisUserInRoleを使う。 - NullPointer's


まるっきり、実装方法が紹介されてました。

前提条件として、ユーザー情報*1はログイン処理後、セッションに保持する。


そして仕組みは


1.HttpServletRequestWrapperを継承して、isUserInRole()メソッドでセッションに保存してあるユーザー情報のロールを戻り値にする
2.フィルターで独自実装のHttpServletRequestを呼び出す。


という感じ。

AuthHttpServletRequest.java
package jp.co.suusuke.servlet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpSession;

public class AuthHttpServletRequest extends HttpServletRequestWrapper {

	/**
	 * @param request
	 */
	public AuthHttpServletRequest(HttpServletRequest request) {
		super(request);
	}

	/* (non-Javadoc)
	 * @see javax.servlet.http.HttpServletRequestWrapper#getRemoteUser()
	 */
	public String getRemoteUser() {
		HttpSession session = this.getSession(false);
		if (session == null) {
			return null;
		}
		return (String) session.getAttribute("auth.user");
	}

	/* (non-Javadoc)
	 * @see javax.servlet.http.HttpServletRequestWrapper#isUserInRole(java.lang.String)
	 */
	public boolean isUserInRole(String str) {
		if (str == null) {
			return false;
		}
		HttpSession session = this.getSession(false);
		if (session == null) {
			return false;
		}

		Object role = session.getAttribute("auth.role");
		return (str.equals(role));
	}

}
AuthFilter.java
package jp.co.suusuke.servlet.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import jp.co.suusuke.servlet.AuthHttpServletRequest;

public class AuthFilter implements Filter {

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.servlet.Filter#destroy()
	 */
	@Override
	public void destroy() {
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest,
	 * javax.servlet.ServletResponse, javax.servlet.FilterChain)
	 */
	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		chain.doFilter(
				new AuthHttpServletRequest((HttpServletRequest) request),
				response);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
	 */
	@Override
	public void init(FilterConfig arg0) throws ServletException {

	}

}
web.xml
<filter>
    <filter-name>authFilter</filter-name>
    <filter-class>jp.co.suusuke.servlet.filter.AuthFilter</filter-class>
</filter>        

...


<filter-mapping>
    <filter-name>authFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

フィルターの順番は先頭*2に設定したんだけど、いいのかな?

後で、デバッグしてみよう。


とりあえず、JDBCRealm使わないでroles属性を有効に使うことができた。

*1:idやロールetc...

*2:encodingfilterの前

検証エラー時に、input先に遷移する前にリクエストに情報を設定する方法。

Seasarメーリングリストで、質問されてました。
Seasar-user:16966)

ひがさんより@Executeのinput属性にメソッドを指定してという返信があって、メソッド指定ができること知らなかったのでメモ。

どういうことか

例えば、アンケート入力画面が有って、アンケートの項目はActionクラスで動的に生成してRequestスコープに設定して画面表示している場合。検証エラー時(アノテーションでの)にアンケートの項目をどのように設定するのかということ。

今まで

@Executeアノテーションのvalidate属性に"@"と表示用のオブジェクトを作るメソッドを作って設定してました。

QuestionAction.java
public class QuestionAction {

  @ActionForm
  @Resource
  protected QuestionForm questionForm;

  public List<QuestionView> questionViewList;

  @Execute(validator = false)
  public String index() {

    // 表示処理(questionViewListの生成)

    return "index.jsp";
  }

  @Execute(validator = true, validate="validate, @", input = "index.jsp")
  public String regist() {

    // 登録処理

    return "regist.jsp";

  }

  public ActionMessages validate() {

    // 表示処理(questionViewListの生成)

    return new ActionMessages();
  }
 


}
QuestionForm.java
public class QuestionForm {

  @Required
  public String[] questions;

}

こうすればよかった

@Executeアノテーションのinput属性に表示用のオブジェクトを生成するメソッドを追加する。

QuestionAction.java
public class QuestionAction {

  @ActionForm
  @Resource
  protected QuestionForm questionForm;

  public List<QuestionView> questionViewList;

  @Execute(validator = false)
  public String index() {

    // 表示処理(questionViewListの生成)

    return "index.jsp";
  }

  @Execute(validator = true, input = "backToIndex")
  public String regist() {

    // 登録処理

    return "regist.jsp";

  }

  @Execute(validator = false)
  public String backToIndex() {

     // 表示処理(questionViewListの生成)
     
     return "index.jsp";

  }

}
QuestionForm.java
public class QuestionForm {

  @Required
  public String[] questions;

}

まとめ

Strutsの場合もinput属性にActionを指定できるのかなと思って、会社にあったStruts インアクションを見てみたら、指定することができますって書いてあった。

こういうのはStrutsしっかり勉強した人は直感的にわかるんだろうなと思いました。