前言
- 权限的粒度可以细细的划分,甚至可以划分到代码中的每个方法上面,只要用户没有权限访问某个CRUD的方法,我们可以将其拦截。
总体思路
- 添加全局的拦截器,拦截用户的请求,判断用户是否有请求此方法的权限,若用户有权限,则放行,若用户没有权限,则拦截,提示用户没有权限使用此功能。
自定义注解代码
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationLimit {
String mid();
String pid();
}
拦截器代码
public class ErrorAndLimitInterceptor extends MethodFilterInterceptor {
/**拦截器*/
@Override
protected String doIntercept(ActionInvocation actioninvocation) throws Exception {
HttpServletRequest request = (HttpServletRequest) actioninvocation
.getInvocationContext().get(StrutsStatics.HTTP_REQUEST);
try {
Object action = actioninvocation.getAction();
String methodName = actioninvocation.getProxy().getMethod();
Method method = action.getClass().getMethod(methodName, null);
String result = null;
boolean flag=isCheckLimit(request,method);
if (flag) {
result=actioninvocation.invoke();
}else{
request.setAttribute("errorMsg", "对不起,您没有权限操作此功能");
return "errorMsg";
}
return result;
} catch (Exception e) {
/**
* 处理异常
*/
String errorMsg = "出现错误信息,请查看日志!";
if (e instanceof RuntimeException) {
RuntimeException re = (RuntimeException) e;
errorMsg = re.getMessage().trim();
}
/**
* 发送错误消息到页面
*/
request.setAttribute("errorMsg", errorMsg);
/**
* log4j记录日志
*/
Log log = LogFactory
.getLog(actioninvocation.getAction().getClass());
log.error(errorMsg, e);
return "errorMsg";
}
}
private boolean isCheckLimit(HttpServletRequest request, Method method) {
if (method==null) {
return false;
}
ElecUser elecUser=(ElecUser)request.getSession().getAttribute("globle_user");
if (elecUser==null) {
return false;
}
Hashtable<String,String> ht =(Hashtable<String, String>) request.getSession().getAttribute("globle_role");
if (ht==null) {
return false;
}
boolean isAnnotationPresent=method.isAnnotationPresent(AnnotationLimit.class);
if (!isAnnotationPresent) {
return false;
}
AnnotationLimit limit=method.getAnnotation(AnnotationLimit.class);
String mid=limit.mid();
String pid=limit.pid();
boolean flag=false;
WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());
IElecRoleService elecRoleService = (IElecRoleService)wac.getBean(IElecRoleService.SERVICE_NAME);
if (ht!=null && ht.size()>0) {
for (Iterator<Entry<String, String>> ite = ht.entrySet().iterator();ite.hasNext();) {
Entry<String,String> entry=ite.next();
String roleId =entry.getKey();
flag=elecRoleService.findRolePopedomByID(roleId,mid,pid);
if (flag) {
break;
}
}
}
return flag;
}
}
拦截器配置
<interceptors>
<interceptor name="errorAndLimitInterceptor" class="com.itheima.elec.utils.ErrorAndLimitInterceptor" />
<interceptor-stack name="myErrorAndLimitInterceptor">
<interceptor-ref name="defaultStack" />
<interceptor-ref name="errorAndLimitInterceptor" >
<param name="excludeMethods">menuHome,title,left,change,loading,logout,alermStation,alermDevice,showMenu
</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="myErrorAndLimitInterceptor"/>
在方法上添加权限的注解
@AnnotationLimit(mid="an",pid="am")
public String home() {
方法体
.......
.......
return "home";
}
小结
- 拦截器中代码的功能是读取方法体上的注解代码,注解代码中存放着访问此方法的权限信息,用户拿到这些权限信息后,再加上自己角色id,然后利用这些信息一块去数据库中检查该用户是否拥有此权限,若有,则放行,反之则拦截。做到这,我们将权限的粒度控制在每个方法上面了,我们再在浏览器中的地址栏中输入Url地址也不会访问到非法页面了。