Webシステムで特定の画面への直アクセス

こちらとセットで使うだろうというネタです。
URLつきメールをメーラーで送信するためのカスタムタグ - おかひろの雑記

業務システムは大抵の場合は認証があるかと思いますが、システムの特定の画面に直アクセスできるURLをクリックした時のことを考えます。

たとえば「/top/selectData」というURLに直アクセスしたとして、認証が必要な場合はまずチェックがかかります。

図中のProxyは、sastruts-extensionのProxyですが、これはFilterとかでも考え方は同じです。

sastruts-extension
sastruts-extensionのActionProxyでログインチェック - おかひろの雑記


Proxyでログインチェックをした際、セッション上にログイン情報があればそのまま該当のURLにアクセス、
ログイン情報がなければログイン画面にリダイレクトします。これは問題無いと思います。

しかしこれでは、ログイン画面にリダイレクトされて、正しいユーザーIDとパスワードでログイン成功しても
メニュー画面に遷移してしまい、アクセスしようとしていたデータ参照画面に遷移しません。

せっかくなら、下図の緑の線のように、アクセスしようとしていたURLにジャンプしたいところです。

そもそもアプリケーションサーバーの認証機能を使う場合はこういった問題はないと思いますが、
Filterやsastruts-extensionなどを使って自前で実装する場合は、考慮しておく必要があるかもしれません。

ここでは、私なりに考えた方法を紹介します。
もっといい方法があれば、教えていただけたら嬉しいです。

仕様
まず、URL指定による直アクセスなのかそうでないのかを明確に区別するようにします。
具体的には、URL指定による直アクセスの場合は「d=true」などのリクエストパラメーターを指定し、
このパラメーターがあれば直アクセス、なければ通常のWebシステム内による画面遷移とします。

また、直アクセスは特定のURLのみ許可するようにします。
上の図の例で言えば、/top/selectData(参照画面)は直アクセスOKだけど、/top/updateData(更新処理)は直アクセスNG・・などのように設定します。

実装
LoginCheckProxy

public class LoginCheckProxy implements ActionProxy
{
	@Resource
	protected LoginUserDto loginUserDto;
	
	@Resource
	protected HttpServletRequest request;
	
	@Resource
	protected Map requestScope;
	
	@Override
	public String execute(ProxyChain proxyChain) throws Exception
	{
		// ダイレクトアクセスかどうか
		String lsDirect = request.getParameter("d");
		
		// ログインされていなければログイン画面に遷移
		if(!loginUserDto.isLogined)
		{
			if(lsDirect != null && lsDirect.equalsIgnoreCase("true"))
			{
				String lsDirectAccessURL = (String)requestScope.get("javax.servlet.forward.servlet_path");
				// 直アクセス用のパラメーターを構築
				String lsDirectAccessParam = "directAccessURL=" + lsDirectAccessURL;
												
				return "/LoginPrev.jsp?" + lsDirectAccessParam;
			}
			
			return "/loginFail.jsp";
		}
		
		// ログインされていれば、次に進む
		return proxyChain.invoke();
	}
}

直アクセスかどうかをリクエストパラメーター"d"により判別します。
直アクセスの場合はそのURLを取得し、ログイン画面に渡すようにします。

LoginPrev.jsp

<script language="javascript">
	var url = '${f:url("/")}?directAccessURL=${param.directAccessURL}';
	location.href = url;
</script>

直アクセスの場合に、ログイン画面の前にJSPをはさんでおきます。
これがないと、ログイン画面でエラーになる場合があります。この原因までは調べていません。。。

Login.jsp

<html:hidden property="directAccessURL"/>

ログインが成功した場合にジャンプするべきURLを持っておきます。

IndexAction#checkLogin

// 直アクセスの場合
if(this.indexForm.isDirectAccess())
{
	// 直アクセスが許可されているメソッドの一覧をプロパティから取得する
	String directAccessAllowMethods[] = sysConfigProperties.getStringArray("directaccess.allowmethod");
	
	for(String directAccessAllowMethod : directAccessAllowMethods)
	{
		// 指定されたアクション名・メソッド名が許可された一覧にあれば、直アクセスする
		if(this.indexForm.directAccessURL.startsWith(directAccessAllowMethod))
		{
			return this.indexForm.directAccessURL + "?redirect=true";
		}
	}
}

入力されたユーザーIDとパスワードが正しかった場合に上記処理を実行するように記述します。

直アクセスできるURLを限定したいので、プロパティファイルにURLを定義しておくようにします。

#直アクセスすることができるURLの一覧(半角カンマ区切り、"/アクション名/メソッド名")
directaccess.allowmethod=/top/selectData,/top/selectHogeData

ここまでで完了です。

まとめ

  • ログインされているかをチェックする処理(ProxyもしくはFilter)
    • ログイン情報がセッションにあれば通過
    • ログイン情報がない場合、リクエストパラメーターで直アクセスかどうかを判別
      • 直アクセスでなければ、普通どおりログイン画面に遷移
      • 直アクセスであれば、リクエストされたURLを渡しつつログイン画面に遷移
  • ログインチェック処理
    • 入力されたユーザーIDとパスワードが正しいかチェック
      • 間違っていれば、ログイン画面に遷移
      • 正しければ、直アクセスURLが指定されているかどうかをチェック
        • 指定されていなければ、メニュー(トップ)画面に遷移
        • 指定されていれば、直アクセス可能なURLかどうかをチェック
          • 直アクセス可能なURLであれば、そのURLに遷移
          • 直アクセス不可なURLであれば、メニュー(トップ)画面に遷移