sastruts-extensionのActionProxyでログインチェック

sastruts-extensionという、SAStrutsの拡張コンポーネントがあります。
SAStruts Extension

この中でAction Proxyという機能があり、ActionProxyクラスを作ってActionもしくはActionのメソッドにアノテーションを設定するだけでログインチェックや権限チェックを行えます。
実案件でも使っていますが、簡単に使えるので非常に重宝しています。

今回使用したバージョン
sastruts-extension-0.3
sa-struts-1.0.4-sp8


設定

creator.dicon

下記一行を追加します。

<component class="jp.ardito.seasar.struts.creator.ProxyCreator"/>

customizer.dicon

proxyCustomizerの定義を追加します。

<component name="proxyCustomizer" class="org.seasar.framework.container.customizer.CustomizerChain">
	<initMethod name="addAspectCustomizer">
		<arg>"aop.traceInterceptor"</arg>
	</initMethod>
	<initMethod name="addAspectCustomizer">
		<arg>"actionMessagesThrowsInterceptor"</arg>
		<arg>true</arg>
	</initMethod>
	<initMethod name="addCustomizer">
		<arg>
			<component class="org.seasar.framework.container.customizer.TxAttributeCustomizer" />
		</arg>
	</initMethod>
</component>

actionCustomizerも一部修正します。

<initMethod name="addCustomizer">
	<arg>
		<!--
		<component class="org.seasar.struts.customizer.ActionCustomizer"/>
		-->
		<component class="jp.ardito.seasar.struts.customizer.A3ActionCustomizer">
			<property name="actionReadOnly">new java.lang.Boolean("false")</property>
		</component>
	</arg>
</initMethod>

ActionCustomizerを変えます。
※すべてのActionにProxyを適用する設定はしていません。
※"Action Field Read Only"の設定はしていません。

struts-config.xml

  <!--
    <controller
        maxFileSize="1024K"
        bufferSize="1024"
        processorClass="org.seasar.struts.action.S2RequestProcessor"
        multipartClass="org.seasar.struts.upload.S2MultipartRequestHandler"/>
    -->
    <controller
        maxFileSize="1024K"
        bufferSize="1024"
	processorClass="jp.ardito.seasar.struts.action.A3RequestProcessor"
        multipartClass="org.seasar.struts.upload.S2MultipartRequestHandler"/>

使い方

チェックプログラム(ActionProxyクラス)

たとえばログイン情報の有無をチェックするだけならこんな感じです。
パッケージは"ルートパッケージ.proxy"、クラス名はXxxProxyとする必要があります。

import javax.annotation.*;
import jp.ardito.seasar.struts.auth.*;
import okahirop.dto.*;

public class LoginCheckProxy implements ActionProxy
{
	@Resource
	protected LoginUserDto loginUserDto;
	
	public String execute(ProxyChain chain) throws Exception
	{
		if(!loginUserDto.logined)
		{
			return "/login?redirect=true";
		}
		
		return chain.invoke();
	}
}

LoginUserDtoのloginedプロパティで判断し、ログインされていない場合はログイン画面にリダイレクトします。
ログインされている場合はchain.invoke()を返して次に進みます。

Actionへの適用

ActionもしくはActionのメソッドに@Proxyアノテーションをつけるだけで、チェック処理を実装することができます。

@Proxy(type=ProxyType.OVERRIDE,proxy=LoginCheckProxy.class)

また、例えばログインチェックのみを行うLoginCheckProxy、権限のチェックを行うRoleCheckProxyを作成して、
複数のチェックを設定することができるようです。

@Proxy(type=ProxyType.OVERRIDE,proxy={LoginCheckProxy.class,RoleCheckProxy.class})

こうするとまずログインチェックが実施され、パスした場合は権限チェックが実施されるという流れになりました。

Actionクラスに@Proxy指定するだけで全メソッドに適用されるので、非常に便利です。


Web画面上でのログインチェックであれば、ログインされていない場合はログイン画面にリダイレクトすればいいですが、
Ajaxなどでアクセスするプログラムの場合は別のProxyを作ったほうがいいと思います。

import javax.annotation.*;
import jp.ardito.seasar.struts.auth.*;
import okahirop.dto.*;

public class LoginCheckForAjaxProxy implements ActionProxy
{
	@Resource
	protected LoginUserDto loginUserDto;
	
	public String execute(ProxyChain chain) throws Exception
	{
		if(!loginUserDto.logined)
		{
			response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
			
			return null;
		}
		
		return chain.invoke();
	}
}

リダイレクトではなく、HTTPステータスコード401(Unauthorized)を返すのが適切ではないでしょうか。

Actionでは、Webページの遷移メソッドとAjax用メソッドが混在する場合があります。
この場合は、例えばActionにはWebページ用Proxy、Ajax用メソッドにはAjax用Proxyを指定するといいと思います。
@ProxyアノテーションのtypeにProxyType.OVERRIDEを指定することで、使用するProxyを上書きすることができます。

詳しくはこちらを参照してください。
https://sites.google.com/site/sastrutsextension/feature/action-proxy