JavaEE权限管理系统的搭建-------使用拦截器实现菜单URL的跳转权限验证和页面的三级菜单权限按钮显示
本小结讲解,点击菜单进行页面跳转,看下图,点击管理员列表后会被认证拦截器首先拦截,验证用户是否登录,如果登录就放行,紧接着会被权限验证拦截器再次拦截,拦截的时候,会根据URL地址上找到对应的方法,然后查询方法上标注的自定义权限注解,紧接着根据当前登录用户查询出所有权限列表,然后进行验证,如果包含对应注解中的权限代码,就放行,否则提示或者跳转到404.
/**
* 进入管理用户列表页面
* @return
*/
@AccessPermissionsInfo("admin:list")
@RequestMapping(value = "/admin-user-list.action",method = RequestMethod.GET)
public String adminUserListPage(HttpSession session,Model model){
//获取session用户是否存在
AdminUser adminUser = (AdminUser)session.getAttribute("adminUser");
if(adminUser!=null){
//根据用户名查询出该用户所有拥有的权限集合,
//这个权限集合查询出来了的集合是一个String集合,查询出来只有一列数据permission.code
List<String> permissions =
permissionService.findAllPermissionByLoginName(adminUser.getLoginName());
model.addAttribute("permissions",permissions);
}
return "admin-user-list";
}
拦截器的拦截过程如下图:
AuthorizationInterceptor类:
package com.supin51.interceptor;
import com.supin51.domain.AdminUser;
import com.supin51.service.PermissionService;
import com.supin51.utils.AccessPermissionsInfo;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
* @Author:ShaoJiang
* @description: 权限认证拦截器
* @Date: created in 下午1:43 2019/1/21
* @Modified By:
*/
public class AuthorizationInterceptor implements HandlerInterceptor {
private static final Log logger = LogFactory.getLog(AuthorizationInterceptor.class);
@Autowired
private PermissionService permissionService;
/*
* return true 才会继续执行下列两个方法(请求继续),否则整个请求结束
* 该方法主要进行拦截处理,该方法在Controller处理之前调用,
* */
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
//获取请求的路径进行判断
String servletUrl = request.getServletPath();
logger.info("权限认证拦截器:preHandle-------->"+servletUrl);
//是否授权,默认为未授权
boolean isAuthorize = false;
//如果方法上有权限注释
if(handler.getClass().isAssignableFrom(HandlerMethod.class))
{
AccessPermissionsInfo permissionsInfo =
((HandlerMethod)handler).getMethodAnnotation(AccessPermissionsInfo.class);
if (permissionsInfo==null||permissionsInfo.value()=="")
{
isAuthorize = true;
logger.info("权限认证拦截器:preHandle-------->不需要权限,可以访问");
}else
{
String permission = permissionsInfo.value().toString();
logger.info("权限认证拦截器:preHandle-------->需要权限:"+permission+"才可以访问");
//获取session中的用户信息
AdminUser adminUser = (AdminUser)request.getSession().getAttribute("adminUser");
//如果用户已登录,放行,否则拦截
if(adminUser!=null){
//根据用户名查询出该用户所有拥有的权限集合
List<String> permissions =
permissionService.findAllPermissionByLoginName(adminUser.getLoginName());
//判断权限集合中的URL字段是否包含请求的路径,如果包含就放行,否则引导至提示(权限不足,请联系管理员)页面
for(String s:permissions)
{
if(permission.contains(s)){
isAuthorize = true;
logger.info("权限认证拦截器:preHandle-------->当前登录用户:"+adminUser.getLoginName()+"有"+permission+"访问权限,验证通过");
break;
}
}
}
}
}
if(!isAuthorize){
logger.info("权限认证拦截器:preHandle-------->权限不足或者无法访问该资源");
//转发至404页面
request.getRequestDispatcher("/404").forward(request,response);
}
return isAuthorize;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
logger.info("权限认证拦截器:postHandle-------->");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
logger.info("权限认证拦截器:afterCompletion-------->");
}
}
自定义注解类
package com.supin51.utils;
import java.lang.annotation.*;
/**
* @Author:ShaoJiang
* @description:自定义权限注解,用于注解在controller方法上,在拦截器中拦截用户是否有权限访问
* @Date: created in 下午8:44 2019/1/22
* @Modified By:
*/
@Inherited
@Target(ElementType.METHOD)//用于方法上的注解
@Retention(RetentionPolicy.RUNTIME)
public @interface AccessPermissionsInfo {
/**
* 权限名称值
* @return 权限名称
*/
String value() default "";
}
持久层PermissionMapper.xml
<!--这个方法获取的权限返回列只有一个code字段,主要用在了拦截器和页面上的按钮权限控制显示-->
<!--对应PermissionDao接口中的findAllPermissionByLoginName方法-->
<select id="findAllPermissionByLoginName" parameterType="string" resultType="string" >
SELECT tp.code
FROM t_admin ta
LEFT JOIN t_admin_role tar
ON tar.adminId = ta.id
LEFT JOIN t_role tr
ON tar.roleId = tr.id
LEFT JOIN t_role_permission trp
ON trp.roleId = tr.id
LEFT JOIN t_permission tp
ON tp.id = trp.permissionId
WHERE ta.loginName = #{loginName}
AND tp.url IS NOT NULL
</select>