自己做一个简单的东东,使用ssh,说实话strut2的拦截器感觉还是比较灵活,由于系统比较简单,权限验证就全部由一个拦截器完成
后来发现,这样做有一个不好的地方,就是验证是action级别的,而不是方法级别的,粒度太大了,我自己的代码又比较乱,最近在看annotation相关的资料,心中一动,就想把验证的改成用annotation来实现,只需要在方法上标注可以调用该方法的角色,就可以了,拦截器的代码如下:
annotation的定义如下:
匿名可访问的方法可以不用标注,如果是"*",表示需要登录的用户才能访问
public class AuthorizeInterceptor implements Interceptor {
private static final long serialVersionUID = 1L;
private static final Log log = LogFactory.getLog(AuthorizeInterceptor.class);
public static final String USR_KEY = "nbrc.user";
public static final String LOGIN_URL = "login";
@Override
public String intercept(ActionInvocation inv) throws Exception {
log.info("AuthorizeInterceptor进入拦截器");
Object action = inv.getAction();
if(action instanceof AuthorizeAction){
//需要验证的action全部实现AuthorizeAction接口
log.info("需要验证的action");
User u = (User) inv.getInvocationContext().getSession().get(USR_KEY);
if(u==null){
log.info("用户信息不存在");
return LOGIN_URL;
}else{
AuthorizeAction author = (AuthorizeAction) action;
author.setUser(u);
//把用户信息放入action上下文
if(author.validateUser()){
//action的validateUser方法判断用户是否有权限
log.info("验证用户通过");
return inv.invoke();
}else{
log.info("验证不通过,用户没有权限");
return LOGIN_URL;
}
}
}else{
log.info("不需要用户验证的action");
return inv.invoke();
}
}
@Override
public void destroy() {
}
@Override
public void init() {
}
}
后来发现,这样做有一个不好的地方,就是验证是action级别的,而不是方法级别的,粒度太大了,我自己的代码又比较乱,最近在看annotation相关的资料,心中一动,就想把验证的改成用annotation来实现,只需要在方法上标注可以调用该方法的角色,就可以了,拦截器的代码如下:
public class AuthorizeInterceptor implements Interceptor {
private static final long serialVersionUID = 1L;
private static final Log log = LogFactory.getLog(AuthorizeInterceptor.class);
public static final String USR_KEY = "nbrc.user";
public static final String USR_LOG_CNT="nbrc.logincount";
public static final String USR_LAST_LOG="nbrc.lastlogin";
public static final String LOGIN_URL = "login";
@Override
public String intercept(ActionInvocation inv) throws Exception {
log.info("AuthorizeInterceptor进入拦截器");
Object action = inv.getAction();
User u = (User) inv.getInvocationContext().getSession().get(USR_KEY);
String method = inv.getProxy().getConfig().getMethodName();
Method m = action.getClass().getMethod(method);
String[] roles = null;
if(m.isAnnotationPresent(AllowRoles.class)){
AllowRoles ar = m.getAnnotation(AllowRoles.class);
roles = ar.roleNames();
if(isAllowed(roles,u)){
log.info("验证用户通过");
return inv.invoke();
}else{
log.info("验证不通过,用户没有权限");
return LOGIN_URL;
}
}else{
log.info("没有Annotation,直接运行");
return inv.invoke();
}
}
private boolean isAllowed(String[] roles, User usr) {
if(roles[0].equals("*") && usr!=null){
log.info("允许用户的权限:*");
return true;
}
if(usr!=null){
String priv = usr.getPriv();
for(String r : roles){
if(r.equals(priv)){
log.info("允许用户的权限:" + r);
return true;
}
}
}
return false;
}
@Override
public void destroy() {
}
@Override
public void init() {
}
}
annotation的定义如下:
@Retention(RetentionPolicy.RUNTIME)
public @interface AllowRoles {
public String[] roleNames();
}
匿名可访问的方法可以不用标注,如果是"*",表示需要登录的用户才能访问
@AllowRoles(roleNames="dangwei")
public String execute(){
//TODO:method here
}