2007年10月28日日曜日

Acegiとの連携2

こちらのInterceptorの方がシンプルだな

tutorial/AuthzInterceptor.java

package tutorial;

import org.acegisecurity.AccessDeniedException;
import org.acegisecurity.taglibs.velocity.Authz;
import org.acegisecurity.taglibs.velocity.AuthzImpl;
import tutorial.acegi.AuthzAware;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;

public class AuthzInterceptor implements Interceptor {
String allowroles;
String denyroles;
public void destroy() {
}

public void init() {
}
public void setAllowedRoles(String allowroles) {
this.allowroles = allowroles;
}
public void setDeniedRoles(String denyroles) {
this.denyroles = denyroles;
}

public String intercept(ActionInvocation invocation)
throws Exception {

Object act = invocation.getAction();
if (allowroles != null || denyroles != null || act instanceof AuthzAware ) {
Authz authz = new AuthzImpl();
if (allowroles != null ) {
if (!authz.anyGranted(allowroles)) {
throw new AccessDeniedException("not allow");
}
}
if (denyroles != null ) {
if (authz.anyGranted(denyroles)) {
throw new AccessDeniedException("deny");
}
}
if (act instanceof AuthzAware) {
AuthzAware authzAware = (AuthzAware)invocation.getAction();
authzAware.setAuthz(authz);
}
}

return invocation.invoke();
}
}

これを struts.xml で

<interceptor name="role_admin"
class="tutorial.AuthzInterceptor">
<param name="allowedRoles">ROLE_ADMIN</param>
</interceptor>

として action で interceptor-ref すればいい

Acegiとの連携

filterは Acegi、 Struts2の順に適用する必要があるが、これだとAcegiのAccessDeniedExceptionがStrutsで処理できない

なので、Struts2の Interceptor として実装した


package tutorial;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.acegisecurity.intercept.AbstractSecurityInterceptor;
import org.acegisecurity.intercept.InterceptorStatusToken;
import org.acegisecurity.intercept.ObjectDefinitionSource;
import org.acegisecurity.intercept.web.FilterInvocation;
import org.acegisecurity.intercept.web.FilterInvocationDefinitionSource;
import org.apache.struts2.ServletActionContext;


import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;

public class AcegiFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Interceptor, FilterChain {
private FilterInvocationDefinitionSource objectDefinitionSource;
private boolean observeOncePerRequest = true;

public void destroy() {
}

public void init() {
}
public Class getSecureObjectClass() {
return FilterInvocation.class;
}
public void doFilter(ServletRequest request, ServletResponse response) throws java.io.IOException,ServletException {
}
public String intercept(ActionInvocation actionInvocation) throws Exception {
HttpServletRequest req = ServletActionContext.getRequest();
HttpServletResponse res = ServletActionContext.getResponse();
FilterInvocation fi = new FilterInvocation(req, res, this );

InterceptorStatusToken token = super.beforeInvocation(fi);

String ans;
try {
ans = actionInvocation.invoke();
} finally {
super.afterInvocation(token, null);
}
return ans;
}

public boolean isObserveOncePerRequest() {
return observeOncePerRequest;
}

public ObjectDefinitionSource obtainObjectDefinitionSource() {
return this.objectDefinitionSource;
}

public void setObjectDefinitionSource(FilterInvocationDefinitionSource newSource) {
this.objectDefinitionSource = newSource;
}

public void setObserveOncePerRequest(boolean observeOncePerRequest) {
this.observeOncePerRequest = observeOncePerRequest;
}
}


として exception の interceptor の後に呼び出す。
すると AccessDeneid exception を struts2 で補足できる。
※Acegiのフィルタチェインには filterSecurityInterceptor を書かない

2007年10月23日火曜日

propertiesファイル

Action に class を記述していないと、アクションクラスやパッケージに関連した properties ファイは読んでくれない。当たり前だけどはまりました。

2007年10月22日月曜日

setXXXX されたくないパラメータ

":" + 名前 とかにすると setXXXX が呼ばれなくなる
例) :del とかの名前をつけるとそれらのパラメータは setが呼ばれなくなるので
 セッターが無いとかのエラーがいちいち出なくていい

2007年10月21日日曜日

s:paramのvalue

<s:param name="id" value="xxx">

xxxは expressionなので普通の文字列を設定したい場合は

<s:param name="id">xxx</s:param>
とする。