在学习了struts2框架后,我萌生了一个想法:可不可以使用包(package)分配权限,而在拦截器中拦截到请求来检测权限是否足够?
ps:希望大家和我一样喜欢多思考。不过在很长一段时间中我都以为是自己发明了这个技术……实际上很多项目都很好地应用了,只是一个小技巧而已……
废话不多说,我先将struts.xml配置贴上来大家看看:
1 2 34 5 6 7 8 9 41 4210 1611 12 1513 14 17 18 19 23/WEB-INF/page/error.jsp 20toLogin 21viewAllSubjects 2224 26/WEB-INF/page/error.jsp 2528 30/index.jsp 2932 34/WEB-INF/page/view.jsp 3335 37/WEB-INF/page/vote.jsp 3638 40/index.jsp 3943 59 6045 48/WEB-INF/page/reg_success.jsp 46/WEB-INF/page/register.jsp 4749 52viewAllSubjects 50/WEB-INF/page/login.jsp 5153 55/WEB-INF/page/register.jsp 5456 58/WEB-INF/page/login.jsp 5761 8162 64/WEB-INF/page/saveorupdate.jsp 6366 69/WEB-INF/page/vote_success.jsp 67vote 6871 73/WEB-INF/page/saveorupdate_success.jsp 7274 76/WEB-INF/page/saveorupdate.jsp 7578 80/WEB-INF/page/manage.jsp 79
上文就用包(package)将不同角色的可做操作“圈”到了一起。
ps:上文是一个在线投票系统的配置,在做项目时并未加入Spring,因为还没学……
默认包中有一些公共的属性和普通用户需要登录后才能进行的操作,实际上你可以使用多个包或使用嵌套的方式来约定包。
而上文引用的拦截器定义如下:
1 package web.interceptor; 2 3 import java.util.Arrays; 4 import java.util.Map; 5 6 import org.apache.struts2.dispatcher.Dispatcher; 7 8 import orm.VoteUser; 9 10 import com.opensymphony.xwork2.Action;11 import com.opensymphony.xwork2.ActionContext;12 import com.opensymphony.xwork2.ActionInvocation;13 import com.opensymphony.xwork2.config.entities.PackageConfig;14 import com.opensymphony.xwork2.interceptor.AbstractInterceptor;15 16 /**17 * 缺省或默认的拦截器,用于拦截用户的未授权权请求 例如未登录用户的各种操作和普通用户的权限分配18 * 19 * @author Johness20 * 21 */22 public class DefaultInterceptor extends AbstractInterceptor {23 24 private static final long serialVersionUID = -2780681965998483504L;25 26 /**27 * 常量值:表示用户用于登录和注册时请求的控制器所在包名 此值可以作为配置参数获取,而此处使用了固定值28 */29 private static final String PACKAGE_NAME_LOGINANDREGISTER = "loginandregister";30 /**31 * 常量值:表示用于管理员用户的特殊权限 此值可以作为配置参数获取,而此处使用了固定值32 */33 private static final String PACKAGE_NAME_ADMINRIGHTS = "adminrights";34 35 /**36 * 登录或注册的请求“动作” 已登录用户不需要进行这些请求 此数组维护的控制器名称需要依靠上文的参数动态获取37 */38 private static String[] loginAndRegister;39 /**40 * 管理员权限“动作” 普通用户不能越权 此数组维护的控制器名称需要依靠上文的参数动态获取41 */42 private static String[] adminRights;43 44 /**45 * 为上文数组填充数据 此方法中使用了一些固定值46 */47 public void preData() {48 Mapmap = Dispatcher.getInstance()49 .getConfigurationManager().getConfiguration()50 .getPackageConfigs();51 PackageConfig lar = map.get(PACKAGE_NAME_LOGINANDREGISTER);52 if (null != lar && lar.getActionConfigs().size() > 0)53 loginAndRegister = lar.getActionConfigs().keySet()54 .toArray(new String[] {});55 else56 loginAndRegister = new String[] { "toRegister", "toLogin",57 "register", "login" };58 PackageConfig ar = map.get(PACKAGE_NAME_ADMINRIGHTS);59 if (null != ar && ar.getActionConfigs().size() > 0)60 adminRights = map.get(PACKAGE_NAME_ADMINRIGHTS).getActionConfigs()61 .keySet().toArray(new String[] {});62 else63 adminRights = new String[] { "addSubject", "saveSubject",64 "modifySubjects", "modify" };65 66 // 因为要使用二分查询,所以必须排序67 Arrays.sort(loginAndRegister);68 Arrays.sort(adminRights);69 }70 71 @Override72 public String intercept(ActionInvocation arg0) throws Exception {73 // 登录用户74 VoteUser logUser = (VoteUser) ActionContext.getContext().getSession()75 .get("logUser");76 // 请求的控制器名称77 String actionName = ActionContext.getContext().getName();78 79 // 如需要,则填充数据80 if (null == loginAndRegister)81 this.preData();82 83 // 如果用户没用登录且并不请求登录或注册,则请用户登录84 if (null == logUser85 && Arrays.binarySearch(loginAndRegister, actionName) < 0)86 return Action.LOGIN;87 // 如果用户已经登录并请求登录或注册或者普通用户请求管理员操作,则忽略用户请求88 if (Arrays.binarySearch(loginAndRegister, actionName) >= 0 || (logUser89 .getVuVersion() == 0 && Arrays.binarySearch(90 adminRights, actionName) >= 0))91 return "toIndex";92 return arg0.invoke();93 }94 }
值得一提的是上文的拦截器属性可以不定义为静态,但是通过struts得到包和包内控制器名称的方法在我的印象中似乎不能写在静态块中(也许我记忆有误)。而数据填充方式大家可以自定义,此类在一个Web进程中有一个实例即可。
代码肯定是有待改进,不过好歹也是自己想到的并做到了,鼓励一下吧。
欢迎您移步我们的交流群,无聊的时候大家一起打发时间:
或者通过QQ与我联系:
(最后编辑时间2012-12-26 15:41:53)