Struts1运用Java注解实现简单的权限控制

来源:互联网 发布:知乎赞同最多 编辑:程序博客网 时间:2024/04/30 07:21

看到标题,不要以为看错,没错,就是Struts1!
对于一个目前只能编码的人来说,在公司做项目,技术框架基本不会是你自己决定的。唉,最近的一个项目,他们要求就是要用Struts1,对于我刚接触Struts就是版本2的人来说,Struts1几乎就没再关注过,而且大家也应该都了解Struts1与Struts2的区别到底有多大。一把辛酸泪,就不多说了。
闲话不说,先说下需求。
由于项目规模不大,要求加入简单的权限管理,要求是,
1.不同权限角色进入系统后,显示对应权限的菜单项;
2.后台的Action请求加入权限控制
数据表有客户提供,用户表里只是简单的放入了role字段以区分用户角色。取值为0-5。
前台的菜单项显示与隐藏的控制使用js动态生成,这里主要讲后台的实现,所以前台就简单描述一下。实现方式是定义一个多维数组,存入需要的一级和二级菜单信息,然后解析数组,生成自己想要的格式,利用js拼成html标签。
重点说下后台的实现。后台的实现,一开始我也没想到使用Java的注解,看到这个方法要感谢新浪的一篇博文,使用struts1+注解做权限管理。思路简单来说就是,在调用每个Action之前判断权限,有则放行,无则拦截。
对于Struts1来说,工作流程是:ActionSerlvet接收客户Http请求,使用ActionForm Bean自动填充客户送来的表单数据到ActionForm Bean对象中;根据配置信息(struts_config.xml)将请求分发给相应的Action对象,Action对象调用execute()方法处理请求(根据JavaBean和ActionForm取得业务逻辑和表单数据),并反回ActionForward对象给ActionSerlvet对象,根据ActionForward对象的信息(目标页面),ActionServlet再次将Http请求导航到目标页面,并发送到客户端。
因此,判断出请求处理器ActionSerlvet的哪个方法调了action,就是关键所在了。通过调试断点放在ActionServlet的dopost方法上,发现是processActionPerform调用的action,剩下的就是重写这个方法就好了。当然要记得在xml文件中配置controller标签,指定用自己的请求处理器。
下面通过代码具体实现来说明。
首先,定义Java注解类,Java注解的相关知识这里不是重点,也不多提。
定义一个注解,即一个权限的数组。

import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * 权限控制,注解类 * 生成策略:运行时  * 注解位置:方法  * @author wangxx * */@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface <span style="font-family: Arial, Helvetica, sans-serif;">SystemPrivilegeAnnotation </span>{    String[] privilegeValue();// 权限值}

然后,根据前面的分析,重写RequestProcessor的processActionPerform方法。根据注释应该也能看的明白。

import java.io.IOException;import java.lang.reflect.Method;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.struts.action.Action;import org.apache.struts.action.ActionForm;import org.apache.struts.action.ActionForward;import org.apache.struts.action.ActionMapping;import org.apache.struts.action.ActionMessage;import org.apache.struts.action.ActionMessages;import org.apache.struts.action.RequestProcessor;import org.apache.struts.actions.DispatchAction;import org.apache.struts.actions.MappingDispatchAction;/** * 权限管理器 *  *  * 步骤: * 1、要判断调用的是action的哪个方法,通过反射 *  一般action有三种方式: *      第一,直接继承Action的action,那么方法名就是“execute”; *      第二,继承DispatchAction的action,那么方法名就是request域中对应的mapping中的parameter; *      第三,继承MappingDispatchAction的action,那么方法名就是mapping中的parameter *  通过反射得到调用action的哪个方法 * 2、判断调用的方法上面有没有注解,也就是调用这个方法需不需要权限, *  不需要,调用超类的processActionPerform; *  需要的话,检查用户的权限是否contains这个权限,是就放行,不是不放行 *  * @author wangxx * */public class PrivilegController extends RequestProcessor {    /*     * 断点在ActionServlet的dopost方法上, 发现是processActionPerform调用的action     *      * @see     */    @Override    protected ActionForward processActionPerform(HttpServletRequest request,            HttpServletResponse response, Action action, ActionForm form,            ActionMapping mapping) throws IOException, ServletException {        //判断权限        if (!systemPrivilege(request, action, mapping)) {            ActionMessages messages = new ActionMessages();            messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(                    "error.no.permission"));            saveErrors(request, messages);            //request.setAttribute("org.apache.struts.action.ERROR", "您没有权限进行当前操作!");            //重定向到login            // request.setAttribute("toUrl", SiteURL.getUrlByKey("logon"));            return mapping.findForward("nonpermission");        }        return super.processActionPerform(request, response, action, form,                mapping);    }    // 权限判断方法,返回true说明当前用户有权限调用当前方法    private boolean systemPrivilege(HttpServletRequest request, Action action,            ActionMapping mapping) {        // 拿到方法的名字        String currentMethodName = getCurrentMethodName(request, action,                mapping);        // 拿出方法中的注解信息        SystemPrivilegeAnnotation systemPrivilegeAnnotation = getMethodSystemPrivilegeAnnotation(                action, currentMethodName);        // 如果注解信息为空说明当前方法不需要任何权限        if (systemPrivilegeAnnotation == null) {            return true;        }        //有注解,即需要权限        // 根据注解信息建立权限对象,即当前方法所需权限        String[] privilegeValue = systemPrivilegeAnnotation.privilegeValue();        // 拿出当前用户--也可以存在session,总之这一步是为了取得当前登录者的信息        UserInfo userInfo = (UserInfo) request.getSession().getAttribute(                ConstApp.SESSION_USERINFO);        String userRole = userInfo.getUserRole();        //循环,将当前用户的所有权限逐个与当前方法所需权限相比较        for (String role : privilegeValue) {            if(role.equals(userRole)){                return true;            }        }        return false;    }    /**     * 取得当前action方法的名字     *      * @param request     * @param action     * @param mapping     * @return     */    private String getCurrentMethodName(HttpServletRequest request,            Action action, ActionMapping mapping) {        // 继承DispatchAction的action,那么方法名就是request域中对应的mapping中的parameter        if (DispatchAction.class.isAssignableFrom(action.getClass())) {            return request.getParameter(mapping.getParameter());        }        // 继承MappingDispatchAction的action,那么方法名就是mapping中的parameter        if (MappingDispatchAction.class.isAssignableFrom(action.getClass())) {            return mapping.getParameter();        }        // 直接继承Action的action,那么方法名就是“execute”;        return "execute";    }    /**     * 通过反射得到action方法的注解信息     * @param action     * @param methodName     * @return     */    private SystemPrivilegeAnnotation getMethodSystemPrivilegeAnnotation(            Action action, String methodName) {        try {            // 第二个参数是所求方法的参数列表            Method method = action.getClass()                .getMethod(methodName,new Class[] { ActionMapping.class,                        ActionForm.class, HttpServletRequest.class,HttpServletResponse.class });            if (method != null) {                if (method.isAnnotationPresent(SystemPrivilegeAnnotation.class)) {                    return method.getAnnotation(SystemPrivilegeAnnotation.class);                }            }        } catch (Exception e) {            e.printStackTrace();        }        return null;    }    /**     * 显示错误消息     * @param request     * @param errors     */    protected void saveErrors(HttpServletRequest request, ActionMessages errors)    {        if(errors == null || errors.isEmpty())        {            request.removeAttribute("org.apache.struts.action.ERROR");            return;        } else        {            request.setAttribute("org.apache.struts.action.ERROR", errors);            return;        }    }}

第三,别忘了在配置文件struts-config.xml添加controller。

<controller processorClass="common.PrivilegController" contentType="text/html;chatset=utf-8"></controller>  

最后,在需要权限的Action中添加注解就可以。privilegeValue中设置权限值即可。

/** * 用户密码修改初期化 *  * @author wang * */public class ChangePasswordAction extends Action{    /*     * 用户密码修改初期化     *      * @see     */    @SystemPrivilegeAnnotation(privilegeValue = {"0","1","2","3","4"})    @Override    public ActionForward execute(ActionMapping mapping, ActionForm form,            HttpServletRequest request, HttpServletResponse response)            throws Exception {        。。。。。    }}

至此,Struts1利用Java注解进行权限控制就基本完成了,思路基本就是如此,方法不一定最好,但是实现需求就好!
最后,这只是在工作中遇到的一个小问题,不一定具有普遍性,自己能力也有限,目前实现的方式就是这样,如果想到好的会做补充。

1 0
原创粉丝点击