ãã®èšäºã®ç®çã¯ãæ¿èªãšãŠãŒã¶ãŒèªèšŒã®ã¿ã¹ã¯ãåŒãåããããã³ã³ãããã¬ãŒã ã¯ãŒã¯ãèšè¿°ããã¯ã©ã€ã¢ã³ãããã°ã©ã ã§æå°éã®ã³ãŒããèšè¿°ã§ããããã«ããããšã§ãã ããã«äºçŽããŸããå®éã«ã¯ãSpring Securityã䜿çšããŠããŸãïŒä»¥åã¯ãã®ãããžã§ã¯ãã¯AcegiãšåŒã°ããŠããŸããïŒã
ãã®èšäºã¯ããã®ãããªãœãªã¥ãŒã·ã§ã³ã®ä»äºã®éæ³ãèªåèªèº«ã§è§£ãæãããã人ããŸãã¯äœããã®çç±ã§å
¬çã«å©çšå¯èœãªãœãªã¥ãŒã·ã§ã³ã䜿çšããã»ãã¥ãªãã£ã·ã¹ãã ã®ç¬èªã®å®è£
ãäœæããããšãé©åãšã¯èããŠããªã人ã察象ãšããŠããŸãã ãããã®çç±ã®1ã€ã¯ãRAMãµã€ãºã®å¶éãšãAndroidãªã©ã®Javaç°å¢ã§ãã¢ãã«ãããã¬ãŒã ã¯ãŒã¯ãå®è¡ã§ããªãããšã§ãïŒAndroidãã©ãããã©ãŒã ã§ã®AspectJã®äœ¿çšã«é¢ããããŒã¿ã¯ãããŸããããããã¯æéã®åé¡ã§ãïŒã
ä»ã®ããŒã ã§ã©ã®ããã«ã¢ãããŒã·ã§ã³ã䜿çšããããšã«æ¶æ¥µçãã¯ããããŸãããããã®ã€ãããŒã·ã§ã³ã¯ããŒãžã§ã³1.5ã§Javaèšèªã«è¿œå ãããŸããã 7幎ãéããããã§ãã ïŒããã³Microsoft.NETã®ãã¬ãã¢ã®ã»ãŒ10幎åŸ-æåã¯ã¢ãããŒã·ã§ã³ïŒå±æ§ïŒããããŸããïŒã ç§ã¯èªãããç§ã¯ããããèªåã§æžãã ãã誰ãç¥ããªãã ã»ãšãã©ã®å Žåããã§ã«ååšããã©ã€ãã©ãªã䜿çšããŸãã ãããããã©ããªç¶æ³ã§èªåãæ¬åœã«åœ¹ç«ã€ã®ããç解ããŠãã人ã¯ããŸãããªãããã§ãããã ç解ããã«ã¯7幎ã§ååã§ã-ã¢ãããŒã·ã§ã³ã¯1æ¥ã®æµè¡ã§ã¯ãããŸããã JavaãCïŒãããæ¶ããããšã¯ãªãããã§ãã 圌ãã¯é·ãéJavaã«ãšã©ãŸããšæããŸãã
ã¢ãããŒã·ã§ã³ã«ã¯é倧ãªæ¬ ç¹ããããŸãïŒã³ã³ããïŒæãåçŽãªå Žåãnewã䜿çšããŠäœæããããªããžã§ã¯ããè¿ããã¢ã¯ã·ã§ã³ãå®è¡ããã¡ãœããïŒãã¢ãããŒã·ã§ã³ä»ãã¡ãœãããã¡ãœãããã©ã¡ãŒã¿ãŒããŸãã¯ã¯ã©ã¹ãã£ãŒã«ããèŠã€ããããã«ããã¹ãŠã®ã¡ãœãããšãã£ãŒã«ããã«ãŒãããŠã泚éãä»ããããŠãããã©ããã確èªããå¿
èŠããããŸãã ããã«ããããªããžã§ã¯ãã®åæåæéãšããã°ã©ã ã®èµ·åæéãé·ããªããŸãã éåžžãç¹å®ã®ã¿ã€ããæã€æ³šéã«å«ãŸããã¡ã¿ããŒã¿ã¯ãã£ãã·ã¥ãããŸããããªããžã§ã¯ãã®åæåæéã倧å¹
ã«å»¶é·ããã«æ³šéã䜿çšããå¥ã®æ¹æ³ããããŸãã
æçµçµæããå§ããŸãããã å°ããªãã¹ã¯ãããã¢ããªã±ãŒã·ã§ã³ã®å Žåãç¹å®ã®ã¡ãœãããå®è¡ããããã®ãŠãŒã¶ãŒæš©éããã§ãã¯ããã»ãã¥ãªãã£ã·ã¹ãã ãäœæããå¿
èŠããããŸããã ãã®é -EJB3ãJBoss SeamãSpringã§ã®å®éšãæåããåŸããŠãŒã¶ãŒæš©éã®ãã§ãã¯ããã©ã³ã¶ã¯ã·ã§ã³å¢çã®æ±ºå®ãªã©ãç°ãªãå
¬åŒãªãã³ã»ã³ã¹ã§ããã°ã©ã ã³ãŒããè©°ãŸãããããšãªããã³ãŒããèšè¿°ãã宣èšçãªããªãã¯ã«æ
£ããããšãã§ããŸããããã³ãªã³ã¯äŸåé¢ä¿ç®¡çã ç§ã®ããã°ã©ã ã®EJB3ããã³Spring Securityãšåæ§ã«ã
Allowã¢ãããŒã·ã§ã³ïŒERole.ADMINïŒãç«ã€ã¡ãœããã¯ããŠãŒã¶ãŒïŒçŸåšã®å®è¡ã¹ã¬ããïŒã
Allowã¢ãããŒã·ã§ã³ãã©ã¡ãŒã¿ãŒã§æå®ãããæš©éãã€ãŸãERole.ADMINãæã€å Žåã«ã®ã¿å®è¡ãããããšã«ããŸããã ç°¡åã«ããããã
èš±å¯ ïŒERole.USERïŒãš
èš±å¯ ïŒERole.ADMINïŒã®2çš®é¡ã®æš©å©ã®ã¿ããããŸãã
ãµã³ãã«ã¯ã©ã¹ã®1ã€ã¯æ¬¡ã®ããã«ãªããŸãã
package eu.vitaliy.testaspectjsecurity;
public class ClassA {
public void mWithoutPermission()
{
System. out .println( "Method ClassA.mWithoutPermission()" );
}
@Allow({ ERole.USER, ERole.ADMIN})
public void mUserAndAdmin()
{
System. out .println( "Method ClassA.mUser()" );
}
@Allow(ERole.ADMIN)
public void mAdmin()
{
System. out .println( "Method ClassA.mAdmin()" );
}
}
ã¯ã©ã¹å
šäœã«æ³šéãä»ããå Žåãå¥ã®æ¹æ³ãå¯èœã§ãã 次ã«ãã¯ã©ã¹ã®ãã¹ãŠã®ã¡ãœããã«é©åãªæš©éãå¿
èŠã§ãããå®è¡ããããã«ç¹å¥ãªæš©éãå¿
èŠãšããã¡ãœãããåå®çŸ©ã§ããŸãã
package eu.vitaliy.testaspectjsecurity2;
import eu.vitaliy.testaspectjsecurity.ERole;
import eu.vitaliy.testaspectjsecurity.Allow;
@Allow(ERole.USER)
public class ClassB {
public void mUser1()
{
System. out .println( "Method ClassB.mUser1()" );
}
public void mUser2()
{
System. out .println( "Method ClassB.mUser2()" );
}
@Allow(ERole.ADMIN)
private void mAdmin()
{
System. out .println( "Method ClassB.mAdmin()" );
}
}
ããã¯ãã¢ãããŒã·ã§ã³ã®å®çŸ©ãã©ã®ããã«èŠãããã§ãïŒ
package eu.vitaliy.testaspectjsecurity;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @ interface Allow {
ERole[] value () default {ERole.USER};
}
ERoleåæã«äŸåããŸãã
package eu.vitaliy.testaspectjsecurity;
public enum ERole {
ADMIN,
USER
}
ãã©ãã«ã®äŸã§ã¯ããŠãŒã¶ãŒæš©éãæ ŒçŽãããåçŽãªPermissionStoreã¹ãã¬ãŒãžã䜿çšãããŸãã
ãã®äŸã§ã¯ããŠãŒã¶ãŒæš©éãæ ŒçŽãããåçŽãªPermissionStoreã¹ãã¬ãŒãžã䜿çšããŸããŠãŒã¶ãŒã«é©åãªæš©éããªãå Žåãjava.lang.RuntimeExceptionã®ç¶æ¿è
ã§ããMySecurityExceptionãã¹ããŒãããŸãã
package eu.vitaliy.testaspectjsecurity;
import java.util.HashSet;
import java.util.Set;
public class PermissionStore {
private static Set<ERole> permissions = new HashSet<ERole>();
public static void addPermission(ERole role)
{
permissions.add(role);
}
public static boolean check(ERole role)
{
return permissions.contains(role);
}
}
ãããŠããããäž»ãªæ¹æ³ã§ãã
package eu.vitaliy.testaspectjsecurity;
import eu.vitaliy.testaspectjsecurity2.ClassB;
public class Main {
public static void main( String [] args)
{
/*
* ,
* MySecurityException
*/
PermissionStore.addPermission(ERole.USER);
PermissionStore.addPermission(ERole.ADMIN);
ClassA a = new ClassA();
a.mUserAndAdmin();
a.mWithoutPermission();
a.mAdmin();
ClassB = new ClassB();
c.mUser1();
c.mUser2();
}
}
ããã°ã©ã ãæåŸãŸã§å®äºããã«ã¯ããŠãŒã¶ãŒã«ERole.USERããã³ERole.ADMINã®æš©éãå¿
èŠã§ãã
å®è£
ã«ã€ããŠèª¬æããŸãã ãæ³åã®ãšãããMySecurityExceptionãã¹ããŒãããŠãŒã¶ãŒèªèšŒã³ãŒãã¯ãã®ããã«ã¯æ©èœããŸããã åŸæ¥ã泚éã䜿çšããŠæ§æããããªããžã§ã¯ãã¯ãã³ã³ãããã¡ã¯ããªã䜿çšããŠäœæãããŸããããã¯ãnewæŒç®åã䜿çšããŠãªããžã§ã¯ããäœæãããšããŠãŒã¶ãŒæš©éã確èªããããã®è¿œå æé ãå¿
èŠã«ãªãããã§ãã ã¢ãããŒã·ã§ã³ã®ã¯ã©ã¹ã¹ãã£ã³ãåé¿ããã®ã«åœ¹ç«ã€ãã¯ãããžãŒã¯AspectJãšåŒã°ããŸããããŸãAspectJã䜿çšããã«ã以åãšåæ§ã«å°ãã¬ãã¥ãŒãè¡ãå¿
èŠããããŸãã ãããããŸãé¢çœããªãå Žåã¯ãæ¹æ³3-AspectJã䜿çšããå®è£
ã«é²ãããšãã§ããŸãã
æ¹æ³1 Java Reflection APIïŒJ2SE 1.3以éïŒïŒ
java.lang reflect.Proxyããã³
java.lang.reflect.InvocationHandlerã䜿çšããŠãã¯ã©ã¹ãšåãã€ã³ã¿ãŒãã§ãŒã¹ãå®è£
ããåçãããã·ãªããžã§ã¯ããäœæã
ãŸã ã
Objectã¡ãœãã
java.lang.reflect.InvocationHandler.invokeïŒãªããžã§ã¯ããããã·ãã¡ãœããã¡ãœããããªããžã§ã¯ã[] argsïŒã§ ãã¡ãœããã«
Allowã¢ãããŒã·ã§ã³ãä»ããããŠãããã©ãããå€ã®å
容ãšããã€ãã®PermissionStoreïŒæ
å ±ãä¿åãããŠããå Žæãæš©éããŠãŒã¶ãŒïŒMySecurutyExceptionãã¹ããŒããŸãïŒãŸãã¯ã¹ããŒããŸããïŒã
ãã®æ¹æ³ã®æ¬ ç¹ïŒ
1.ãªããžã§ã¯ãã®äœæã®ããã®ãªãŒããŒãããã
2.åã¡ãœãããåŒã³åºããªãŒããŒãããã
3.ã¯ã©ã¹ã¯äœããã®ã€ã³ã¿ãŒãã§ãŒã¹ãå®è£
ããå¿
èŠããããŸãã
4. InvocationHandlerã¯ã©ã¹ã®
invokeã¡ãœããã¯ãã»ãã¥ãªãã£ãã§ãã¯ãå¿
èŠãšããªãã¡ãœãããå«ããã¹ãŠã®ã¡ãœããã«å¯ŸããŠåŒã³åºãããŸãã æ€èšŒããå¿
èŠãããã¯ã©ã¹å
ã®ã¡ãœããã®æ°ãå°ãªãå Žåãå¥ã®ç¡é§ãªãªãŒããŒãããã
æ¹æ³2
CGLIBã©ã€ãã©ãª-å®è¡æã«ã³ãŒãã®ãã€ããçæããããã®ã©ã€ãã©ãªã
ãªããžã§ã¯ãã®ãããã·ã¡ãœããã®åŒã³åºãã倧å¹
ã«
é«éã«å®è£
ãããŠããŸãã åºæ¬çã«ãããã¯åå°ãããé©åœçãªãã®ã§ã¯ãããŸããã æ¬ ç¹ã¯ãã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ããªããããã·ãªããžã§ã¯ããäœæã§ããããšãé€ããŠãæ¹æ³1ãšåãã§ãã
æ¹æ³3 AspectJã¯ãã¢ã¹ãã¯ãããã°ã©ãã³ã°æ§é ãè¿œå ããJavaèšèªæ¡åŒµæ©èœã§ãã çµæã®ã³ãŒãã¯ãæšæºã®Javaä»®æ³ãã·ã³ãšå®å
šã«äºææ§ããããŸãã AspectJã¯ãã³ã³ãã€ã«æã«ã»ãã¥ãªãã£æ€èšŒã³ãŒããæ¿å
¥ããèšå®å¯èœãªãã¹ã¯ã«ãã£ãŠèå³ã®ããã¡ãœãããèŠã€ããã¯ã€ã«ãã«ãŒãïŒ1ã€ä»¥äžã®ä»ã®æåã眮ãæããããã«äœ¿çšãããæåïŒãèš±å¯ããŸãã AspectJã®ããã€ãã®ããŒãžã§ã³ãããJavaã¢ãããŒã·ã§ã³ããã¹ã¯ã«å«ããããšãã§ããŸããããã¯ãã»ãã¥ãªãã£ã¢ããã€ã¹ãé©çšããããã«ã¡ãœããã«ãã¬ãã£ãã¯ã¹ãä»ããå¿
èŠããããããã¯ããã«äŸ¿å©ã«ãªããŸããã
* * .secure *ïŒ..ïŒ
äžã§è¿°ã¹ãããã«ãæ€èšŒã³ãŒãã¯ã³ã³ãã€ã«æã«æ¿å
¥ãããŸãã ããã¯ã¢ã¹ãã¯ããã³ãã³ã³ãã€ã©ã«ãã£ãŠè¡ãããŸãããã®å
¥åã¯ã³ã³ãã€ã«ããããã€ãã³ãŒãã§ãããæäœã®ããžãã¯ãå€æŽãããªã©ããœãŒã¹ã³ãŒããªãã§åçšã³ãŒããã¢ã¹ãã¯ãããããšãã§ãããããééããªã䟿å©ã§ãã ãã®ããããã®ã¢ãããŒãã«ã¯ãæåã®æ¹æ³ã®æ¬ ç¹1ã2ã4ã¯ãããŸããã
AspectJã®åºæ¬çãªæ§æåäœã¯ã¢ã¹ãã¯ãã§ãã ã¢ã¹ãã¯ããšã¯ãå
¥åã³ãŒãã®äº€å·®ç¹ã«é©çšã§ããäžé£ã®ã«ãŒã«ïŒã¢ããã€ã¹ïŒã§ãã ããã«ã1ã€ã®ã«ãŒã«ãè€æ°ã®äº€å·®ç¹ã«é©çšã§ããŸãã ããŒãã®äº€å·®ç¹ãžã®æ¥ç¶ã¯ããçµåç¹ããšåŒã°ããŸãã
ããŠãŒã¶ãŒæš©éã®ç¢ºèªãæ©èœãå®è£
ããããã«äœ¿çšããSecurityAspectã¢ã¹ãã¯ãã³ãŒãïŒSecurityAspect.ajãã¡ã€ã«ïŒããå§ããŸãããã
package eu.vitaliy.testaspectjsecurity.aspects;
import eu.vitaliy.testaspectjsecurity.Allow;
public aspect SecurityAspect {
private SecurityAspectHelper helper
= new SecurityAspectHelper();
pointcut byMethod() : execution(@Allow * *.*(..));
pointcut byClass() : execution(* @Allow *.*(..))
&& !execution(@Allow * *.*(..));
before() : byMethod(){
helper.beforeMethod(thisJoinPoint);
}
before() : byClass(){
helper.beforeClass(thisJoinPoint);
}
}
ãã«ããŒã¯ã©ã¹ïŒç§ã¯åžžã«è¿œå ã®ã¯ã©ã¹ã«ã¢ã¹ãã¯ãããžãã¯ãé
眮ããŸããã¢ã¹ãã¯ãã³ãŒãã¯ããéæã§ãã¹ããããããªããŸãïŒïŒ
package eu.vitaliy.testaspectjsecurity.aspects;
import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import eu.vitaliy.testaspectjsecurity.Allow;
import eu.vitaliy.testaspectjsecurity.ERole;
import eu.vitaliy.testaspectjsecurity.PermissionStore;
import eu.vitaliy.testaspectjsecurity.MySecurityException;
enum ESecurytyType
{
CLASS, METHOD
}
public class SecurityAspectHelper {
void beforeMethod(JoinPoint pointcut)
{
before(pointcut, ESecurytyType.METHOD);
}
void beforeClass(JoinPoint pointcut)
{
before(pointcut, ESecurytyType.CLASS);
}
@SuppressWarnings( "unchecked" )
void before(JoinPoint pointcut, ESecurytyType securytyType)
{
MethodSignature methodSignature = (MethodSignature) pointcut.getSignature();
Method method = methodSignature.getMethod();
Class clazz = pointcut.getTarget().getClass();
Allow allow = null ;
if (securytyType == ESecurytyType.CLASS)
{
allow = (Allow) clazz.getAnnotation(Allow. class );
} else {
allow = method.getAnnotation(Allow. class );
}
ERole[] role = allow. value ();
for (ERole r : role)
{
if (!PermissionStore.check(r))
{
throw new MySecurityException( clazz.getName(), method.getName(), r);
}
}
}
}
* This source code was highlighted with Source Code Highlighter .
SecurityAspectã®åŽé¢ã«é¢ããç°¡åãªèª¬æïŒ
pointcutã¯ãã³ãŒãã®ã亀差ç¹ãã§ãã
pointcut byMethodïŒïŒïŒå®è¡ïŒ
Allow * *ã*ïŒ..ïŒïŒ;
-Allowã䜿çšããŠæ³šéãä»ããããã¡ãœããã®äº€ç¹ãå®çŸ©ããŸã
pointcut byClassïŒïŒïŒå®è¡ïŒ*
èš±å¯ *ã*ïŒ..ïŒïŒ&&ïŒå®è¡ïŒ
èš±å¯ * *ã*ïŒ..ïŒïŒ;
-Allowã䜿çšããŠã¯ã©ã¹ã§æ³šéãä»ããããŠããã¡ãœããã®äº€ç¹ãå®çŸ©ããŸããã
Allowã䜿çšããŠæ³šéãä»ããªãã§ãã ããã
ããã€ã¯ãã»ãã¥ãªãã£ãã¬ãŒã ã¯ãŒã¯ãã®ã³ãŒããçŽ45è¡ããã£ãããšã確èªã§ããŸãã
ããã°ã©ã ãã³ã³ãã€ã«ããããã«ãAJDT 2.0.2ãã©ã°ã€ã³ãã€ã³ã¹ããŒã«ãããEclipse 3.5.2 IDEã䜿çšããŸããããããã¯antãŸãã¯mavenã䜿çšããŠå®è¡ã§ããŸã
åç
§ïŒ
ã¢ã¹ãã¯ãæåããã°ã©ãã³ã°ã«é¢ãããŠã£ãããã£ã¢ã®èšäºãã®èšäºã®å®çšçãªãµã³ãã«ãããžã§ã¯ãã