Struts2注解Action方法安全

    技术2022-05-20  64

    用过Spring Security的朋友一定不会陌生,有个@Secured注解,可以将其加在Service层的方法上,保护某个方法的安全,确保只有授权的角色可以调用该方法。

     

    但是,如果要对Struts2的Action方法进行保护呢?看似加注解是个不合理的需求。但是,有些情况下,例如,一个命名空间下用星号匹配有多个角色,而用精确地址匹配又导致数据太多,数据库不太好维护。在这种情况下,如果一个Action地址,确定以后不会太更换访问角色的话,可以考虑用注解来保护。

     

    可以将命名空间下的全部地址匹配为星号。然后用注解保护该命名空间下的个别Action地址。

     

    首先是一个注解类。

    Java代码 @Target(METHOD)   @Retention(RUNTIME)   public @interface ActionRoles {         SysRole[] value();   }   @Target(METHOD) @Retention(RUNTIME) public @interface ActionRoles { SysRole[] value(); }

     

    注解里面是一个枚举类,代表了系统的所有角色枚举。

    然后是Struts2的拦截器,在该拦截器内,通过反射,得到加在Action方法注解上的用户角色数组。其中,还通过SpringSecurityUtils取得当前登录的用户,并拿到登录用户的角色,通过和actionRoles循环比较,得到用户是否有授权。

    Java代码 public class AuthorityInterceptor extends MethodFilterInterceptor {         private static final long serialVersionUID = -1070565846576510701L;         @Override      protected String doIntercept(ActionInvocation actionInvocation) throws Exception {           User currentUser = SpringSecurityUtils.getCurrentUser();           if (currentUser != null) {               try {                   Object action = actionInvocation.getAction();                   ActionProxy actionProxy = actionInvocation.getProxy();                   Method method = action.getClass().getMethod(actionProxy.getMethod());                   ActionRoles actionRoles = method.getAnnotation(ActionRoles.class);                   if (actionRoles != null) {                       boolean authorized = false;                       SysRole[] sysRoles = actionRoles.value();                       for (SysRole sysRole : sysRoles) {                           if (SysRole.equals(currentUser.getRoleName(), sysRole)) {                               authorized = true;                               break;                           }                       }                       if (!authorized) {                           return BaseActionSupport.UNAUTHORIZED;                       }                   }               } catch (NoSuchMethodException e) {                   e.printStackTrace();               } catch (SecurityException e) {                   e.printStackTrace();               }           }           return actionInvocation.invoke();       }   }   public class AuthorityInterceptor extends MethodFilterInterceptor { private static final long serialVersionUID = -1070565846576510701L; @Override protected String doIntercept(ActionInvocation actionInvocation) throws Exception { User currentUser = SpringSecurityUtils.getCurrentUser(); if (currentUser != null) { try { Object action = actionInvocation.getAction(); ActionProxy actionProxy = actionInvocation.getProxy(); Method method = action.getClass().getMethod(actionProxy.getMethod()); ActionRoles actionRoles = method.getAnnotation(ActionRoles.class); if (actionRoles != null) { boolean authorized = false; SysRole[] sysRoles = actionRoles.value(); for (SysRole sysRole : sysRoles) { if (SysRole.equals(currentUser.getRoleName(), sysRole)) { authorized = true; break; } } if (!authorized) { return BaseActionSupport.UNAUTHORIZED; } } } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } } return actionInvocation.invoke(); } }

     

    最后一步,很简单啦,在Struts2的Action方法上面加上注解。

    Java代码 @ActionRoles({SysRole.ROLE_ADMIN, SysRole.ROLE_USER})   public String execute() throws Exception {       return SUCCESS;   }   @ActionRoles({SysRole.ROLE_ADMIN, SysRole.ROLE_USER}) public String execute() throws Exception { return SUCCESS; }

     

    到此,大功告成。还需要简单的配置一下拦截器,这个就不写了。还要注意,需要有一个全局结果页面,用以展示“未经授权”。我的BaseActionSupport.UNAUTHORIZED是转跳到403.jsp页面的。


    最新回复(0)