Struts2注解Action方法安全

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

 

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

 

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

 

首先是一个注解类。

Java代码
  1. @Target(METHOD)   
  2. @Retention(RUNTIME)   
  3. public @interface ActionRoles {   
  4.   
  5.     SysRole[] value();   
  6. }  
@Target(METHOD)
@Retention(RUNTIME)
public @interface ActionRoles {

	SysRole[] value();
}

 

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

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

Java代码
  1. public class AuthorityInterceptor extends MethodFilterInterceptor {   
  2.   
  3.     private static final long serialVersionUID = -1070565846576510701L;   
  4.   
  5.     @Override  
  6.     protected String doIntercept(ActionInvocation actionInvocation) throws Exception {   
  7.         User currentUser = SpringSecurityUtils.getCurrentUser();   
  8.         if (currentUser != null) {   
  9.             try {   
  10.                 Object action = actionInvocation.getAction();   
  11.                 ActionProxy actionProxy = actionInvocation.getProxy();   
  12.                 Method method = action.getClass().getMethod(actionProxy.getMethod());   
  13.                 ActionRoles actionRoles = method.getAnnotation(ActionRoles.class);   
  14.                 if (actionRoles != null) {   
  15.                     boolean authorized = false;   
  16.                     SysRole[] sysRoles = actionRoles.value();   
  17.                     for (SysRole sysRole : sysRoles) {   
  18.                         if (SysRole.equals(currentUser.getRoleName(), sysRole)) {   
  19.                             authorized = true;   
  20.                             break;   
  21.                         }   
  22.                     }   
  23.                     if (!authorized) {   
  24.                         return BaseActionSupport.UNAUTHORIZED;   
  25.                     }   
  26.                 }   
  27.             } catch (NoSuchMethodException e) {   
  28.                 e.printStackTrace();   
  29.             } catch (SecurityException e) {   
  30.                 e.printStackTrace();   
  31.             }   
  32.         }   
  33.         return actionInvocation.invoke();   
  34.     }   
  35. }  
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代码
  1. @ActionRoles({SysRole.ROLE_ADMIN, SysRole.ROLE_USER})   
  2. public String execute() throws Exception {   
  3.     return SUCCESS;   
  4. }  
@ActionRoles({SysRole.ROLE_ADMIN, SysRole.ROLE_USER})
public String execute() throws Exception {
	return SUCCESS;
}

 

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值