大体思想:
当系统启动的时候会将所有权限信息加入到Map集合,URL作为key,有此权限访问该URL的角色作为value;然后具体某个用户登录的时候会首先获取其对应的角色,存到session中;当该用户访问某个具体的URL时会进行角色判断其是否由此权限进行访问。
实现过程:
1.定义拦截器(springmvc-servlet.xml)
<!-- 定义拦截器,判断登陆 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<mvc:exclude-mapping path="/**/*.js" />
<bean class="com.thank.filter.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
2.定义一个类在启动的时候加载所有功能对应的权限
public class FuncCache{
public static Map<String, Object> FUNCTION_MAP = new HashMap<>();
static{
// 如1-交易所 2-机构管理员 24-表示仓库机构有权限
FUNCTION_MAP.put("/warehouse/init", ",1,24,29");
}
}
3.定义拦截方法继承HandlerInterceptorAdapter,在Controller之前执行。该类在springmvc-servlet配置文件配置了,当有请求过来的时候会进行拦截。
public class LogingInterceptor extends HandlerInterceptorAdapter{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response
, Object handler) throws Exception{
String website = request.getScheme() + "://" + request.getServerName()
+ ":" + request.getServerPort() + request.getContextPath();
String referer = request.getHeader("Referer");
if(referer != null && !referer.startsWith(website)){ // 不能通过别的站点链接过来
return false;
}
String servletPath = request.getRequestURI();
if(servletPath.endsWith(request.getContextPath()+"/") ||
servletPath.endsWith(request.getContextPath())){
return true;
}
// 浏览器直接打开login.html,非ajax请求也跳到登陆页面
if(servletPath.contains("/login.html") && (request.getHeader("x-requested-with") == null
|| !request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest"))){
request.getRequestDispatcher("./").forward(request, response);
return false;
}
// 不需要登陆
if((servletPath.contains("/login") || servletPath.contains("/loginIn") ||
servletPath.contains("/loginOut") || servletPath.contains("/externalCall"))
&& (!servletPath.contains("/operation/login"))){
return true;
}
HttpSession session = request.getSession(true);
LoginRsp rsp = (LoginRsp) session.getAttribute(Constants.SESSION_LOGIN_KEY);
if(rsp == null){
// 如果是ajax请求到ajax:error处理
if(request.getHeader("x-requested-with") != null
&& request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")){
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.setContentType("application/json");
PrintWriter pw = response.getWriter();
pw.write("losesession");
pw.flush();
pw.close();
return false;
}
// 如果是正常请求,跳转页面
response.sendRedirect(website);
return false;
}else{
if(rsp.getCode() != Constants.loginSuccess && rsp.getCode() != Constants.loginChange){
// 登陆状态不为成功 一律跳转登入页面
request.getRequestDispatcher("./").forward(request, response);
return false;
}
// 请求判断url,机构角色权限,没有权限跳到common.jsp
if(!checkFuncAuth(rsp, request.getServletPath())){
request.getRequestDispatcher("/blank").forward(request, response);
return false;
}
return true;
}
}
private boolean checkFuncAuth(LoginRsp rsp, String reqPath){
int reletype = rsp.getUser().getReletype();
String rlts = (String)FuncCache.FUNCTION_MAP.get(reqPath);
if(rlts == null){ // 如果不在过滤列表就不过滤
return true;
}
// 子机构或交易所
if(reletype == SysContants.SYS_TYPE_CLIENT){ // 机构
if(rlts.contains("," + reletype + ",")) return true;
String roles = rsp.getOrgztype(); // 拿到机构角色
if(roles == null)
return false; // 建了机构还未配机构角色
String [] roletypes = roles.split(",");
for(String roletype : roletypes){
if(rlts.contains("," + reletype + roletype + ",")){
return true;
}
}
return false;
}else{
return rlts.contains("," + reletype + ",");
}
}
// preHandle返回true,在Controller方法调用之后,并且在DispathcherServlet进行视图渲染之前执行
@Override
public void postHandle(HttpServletRequest request, xxxxx
// preHandler返回true,在DispatcherServlet视图渲染之后执行
@Override
public void afterCompletion(xxxxx
}
4.涉及到的标有
1)系统管理员表(SystemManager):
自增AutoID 用户类型(交易所管理员、机构管理员)ReleType 登录账号 用户姓名 密码 所属机构 ...
2)角色表(SystemManagerRole)
自增AutoID 角色名称 所属机构 角色类型(管理端、交易端)Roletype ...
3)角色用户表(RoleUser)
用户ManagerID 角色RoleID 角色类型
4)功能菜单表(FuncMenuList)
资源代码 资源名 级别 菜单类型 上级资源代码 Url 排序 菜单图标
5)角色菜单表(RoleFuncMenu)
角色权限RoleID 菜单代码ResourceCode
附:亦可以参考此博客https://blog.csdn.net/u011277123/article/details/68940939