权限控制是每一个系统都应该有的一个功能,有些只需要简单控制一下就可以了,然而有些却需要进行更加深入和细致的权限控制,尤其是对于一些MIS类系统,基于方法的权限控制就更加重要了。
用反射和自定义注解来实现基于struts2的方法级别的权限控制的主要思想是这样的。
1.先定义一个用于识别在进行action调用的时候标注该方法调用是否需要权限控制,需要什么样的权限的注解类。该注解类一般会包括两个属性,一个是需要的权限,一个是对应的action。
2.然后就是在需要进行权限控制的action方法上加上该注解类,并标明其应该拥有的权限和对应的action。这样一来在进行action调用的时候可以实现一个 自己定义的interceptor来拦截所有的请求,这样在拦截到请求的时候就可以通过ActionInvocation获取到对应的action类的类文件和对应请求的方法名称,然后利用反射来取得action类文件里面对应的请求方法Method,这样就可通过该Method来判断其是否拥有对应的权限控制注解,即看其是否需要进行权限控制,如果需要进行权限控制,就取得该注解并取得其对应的action名称和需要的权限,然后通过session取得当前的用户,并判断当前用户是否拥有对应的某种权限,如果其拥有该权限则继续往下执行,否则,转到自己处理无权限的机制上去。
下面是一段示例代码:
Authority注解:
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Authority { String action(); String privilege(); }
用于拦截请求判断是否拥有权限的拦截器AuthorityInterceptor:
import java.lang.reflect.Method; import java.util.Date; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.Interceptor; public class AuthorityInterceptor implements Interceptor { /** * */ private static final long serialVersionUID = -4637261955156527951L; @Override public void destroy() { // TODO Auto-generated method stub } @Override public void init() { // TODO Auto-generated method stub } @Override public String intercept(ActionInvocation invocation) throws Exception { // TODO Auto-generated method stub String methodName = invocation.getProxy().getMethod(); Method currentMethod = invocation.getAction().getClass().getMethod(methodName); //如果该方法请求是需要进行验证的时候执行以下逻辑 if (currentMethod.isAnnotationPresent(Authority.class)) { // String currentUser = Util.getCurrentUser(ServletActionContext.getRequest()); //这里可以从session里面取得当前的用户 String currentUser = (String)ServletActionContext.getRequest().getSession().getAttribute("currentUser"); //取得权限验证的注解 Authority authority = currentMethod.getAnnotation(Authority.class); //取得当前请求的注解的action String actionName = authority.action(); //取得当前请求需要的权限 String privilege = authority.privilege(); /** * 然后可以在此判断当前用户是否拥有对应的权限,如果没有可以跳到指定的无权限提示页面,如果拥有则可以 * 继续往下执行。 * ............... * if (拥有对应的权限) { * return invocation.invoke(); * } else { * return "无权限"; * } */ System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++"); System.out.println("用户" + currentUser + "在" + new Date() + actionName); System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++"); } return invocation.invoke(); } }
需要进行权限控制的Action:
import com.opensymphony.xwork2.ActionSupport; public class TestAction extends ActionSupport { /** * */ private static final long serialVersionUID = 4679109342743365308L; @Override @Authority(action="test", privilege="find")//请求该方法的时候需要拥有对test的find权限 public String execute() throws Exception { // TODO Auto-generated method stub return super.execute(); } //请求该方法需要拥有对test的test权限 @Authority(action="test", privilege="test") public String test() { return "test"; } }
在struts2的配置文件里面配置自定义的权限控制拦截器:
<!-- 定义拦截器 --> <interceptors> <!-- 申明自定义的权限控制拦截器 --> <interceptor name="authorityInterceptor" class="com.test.AuthorityInterceptor"/> <!-- 把自定义的权限控制拦截器和默认的拦截器栈加到新的自定义的拦截器栈 --> <interceptor-stack name="myInterceptors"> <interceptor-ref name="authorityInterceptors"/> <interceptor-ref name="defaultStack"/> </interceptor-stack> </interceptors> <!-- 指定新的自定义的拦截器栈为默认的拦截器栈,这样自定义的权限控制拦截器就可以发挥作用了 --> <default-interceptor-ref name="myInterceptors"></default-interceptor-ref>