在上一篇 SpringAOP 实现功能权限校验功能 中虽然用AOP通过抛异常,请求转发等勉强地实现了权限验证功能,但感觉不是那么完美,应该用拦截器来实现才是最佳的,因为拦截器就是用来拦截请求的,在请求层面进行权限验证是最好的时机。

假设下面的请求需要进行权限验证,在请求中通过参数params指定必须带有Helper.PARAM_FUNCTION_ID参数,这样拦截器通过判断是否带有该参数,如果带有则进行权限验证,否则不作处理。

@RequestMapping(value = "/moduleAccess.do",params=Helper.PARAM_FUNCTION_ID, method = RequestMethod.POST, produces="text/html;charset=utf-8")
@ResponseBody
public String moduleAccess(String action,FrmModule module) {
int rs = -1;
try{
if(Helper.F_ACTION_CREATE.equals(action)){
rs = moduleService.access(module,Helper.DB_ACTION_INSERT);
//module.setModuleid(rs);
module = moduleService.selectByPrimaryKey(rs);
}else if(Helper.F_ACTION_EDIT.equals(action)){
rs = moduleService.access(module,Helper.DB_ACTION_UPDATE);
module = moduleService.selectByPrimaryKey(module.getModuleid());
}else if(Helper.F_ACTION_REMOVE.equals(action)){
rs = moduleService.access(module,Helper.DB_ACTION_DELETE);
}else{
return JSON.toJSONString(new Result(false,"请求参数错误:action"));
}
}catch(Exception e){
e.printStackTrace();
return JSON.toJSONString(new Result(false,"操作失败,出现异常,请联系管理员!"));
}
if(rs<0){
return JSON.toJSONString(new Result(false,"操作失败,请联系管理员!"));
}
return JSON.toJSONString(new Result(true,module));
}

那么对应的拦截器就直接用登录验证的那个拦截器即可,SecurityInterceptor

package com.jykj.demo.filter;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView; import com.alibaba.fastjson.JSON;
import com.jykj.demo.entity.SysUser;
import com.jykj.demo.service.SysUserRolePermService;
import com.jykj.demo.util.Helper;
import com.jykj.demo.util.Result;
/**
* 1.此拦截器用于拦截所有请求,用于登录权限验证
* 2.拦截 带 moduleId 参数的请求,在渲染视图之前返回 模块权限值
* @author Administrator
*
*/
public class SecurityInterceptor implements HandlerInterceptor{
@Autowired
SysUserRolePermService sysUserRolePermService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("SecurityInterceptor preHandle:"+request.getContextPath()+","+request.getRequestURI()+","+request.getMethod());
HttpSession session = request.getSession();
if (session.getAttribute(Helper.SESSION_USER) == null) {
System.out.println("AuthorizationException:未登录!"+request.getMethod());
if("POST".equalsIgnoreCase(request.getMethod())){
response.setContentType("text/html; charset=utf-8");
PrintWriter out = response.getWriter();
out.write(JSON.toJSONString(new Result(false,"未登录!")));
out.flush();
out.close();
}else{
response.sendRedirect(request.getContextPath()+"/login");
}
return false;
} else {
Object obj = request.getParameter(Helper.PARAM_FUNCTION_ID);
if(obj==null) return true;//没有带功能参数不需要验证
int functionId = Integer.parseInt(obj.toString());
String rs = sysUserRolePermService.permissionValidate(functionId);
System.out.println("校验结果:"+rs);
if(rs.trim().isEmpty()){
return true;//正常通过
}else{
response.setContentType("text/html; charset=utf-8");
PrintWriter out = response.getWriter();
out.write(JSON.toJSONString(new Result(false,rs)));
out.flush();
out.close();
return false;
}
}
}
//模块权限值
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
/*
Object obj = request.getParameter(Helper.PARAM_MODULE_ID);
System.out.println(Helper.PARAM_MODULE_ID+":"+obj);
if(obj == null) return;//如果没有moduleId 参数,否则什么都不做,否则返回模块权限值
System.out.println("SecurityInterceptor postHandle:"+request.getContextPath()+","+request.getRequestURI()+","+request.getMethod());
SysUser loginUser = (SysUser)request.getSession().getAttribute(Helper.SESSION_USER);
int value = sysUserRolePermService.getModulePerm(loginUser.getUserid(),Integer.parseInt(obj.toString()));
modelAndView.addObject(Helper.MVALUE,value);
*/
} @Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception { } }

拦截器配置不变

 <mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/*"/> <!-- 拦截/ /test /login 等等单层结构的请求 -->
<mvc:mapping path="/**/*.aspx"/><!-- 拦截后缀为.aspx的请求 -->
<mvc:mapping path="/**/*.do"/><!-- 拦截后缀为 .do的请求 -->
<mvc:exclude-mapping path="/login"/>
<mvc:exclude-mapping path="/signIn"/>
<mvc:exclude-mapping path="/register"/>
<bean class="com.jykj.demo.filter.SecurityInterceptor">
</bean>
</mvc:interceptor>
</mvc:interceptors>

这样即实现了对某个功能的权限校验的功能 
客户端发送 /moduleAccess.do 请求,该请求带有参数Helper.PARAM_FUNCTION_ID,其值为某个功能的id 
然后拦截器拦截该请求,判断出带有该参数,则对其进行权限校验,如果未通过,写response给客户端,格式是json的字符串,并返回false表示请求已由本拦截器处理了,不会往下执行(返回true表示正常往下执行)。这样就达到了权限验证的目的。这是相对更优雅的实现方式,最起码比上一篇讲的用AOP来实现更优雅。

另外拦截器的postHandle方法是在控制器执行结束,页面渲染之前执行的,所以可以用来给页面添加或修改model属性。

Spring MVC 使用拦截器优雅地实现权限验证功能的更多相关文章

  1. spring mvc +cookie+拦截器功能 实现系统自动登陆

    先看看我遇到的问题: @ResponseBody @RequestMapping("/logout") public Json logout(HttpSession session ...

  2. Spring mvc登录拦截器

    自己实现的第一个Spring mvc登录拦截器 题目要求:拒绝未登录用户进入系统,只要发现用户未登录,则将用户请求转发到/login.do要求用户登录 实现步骤: 1.在spring的配置文件中添加登 ...

  3. 玩转spring MVC(七)----拦截器

    继续在前边的基础上来学习spring MVC中拦截器的使用,下面通过一个例子来实现(完整项目在这里下载:http://download.csdn.net/detail/u012116457/84334 ...

  4. springboot + 拦截器 + 注解 实现自定义权限验证

    springboot + 拦截器 + 注解 实现自定义权限验证最近用到一种前端模板技术:jtwig,在权限控制上没有用springSecurity.因此用拦截器和注解结合实现了权限控制. 1.1 定义 ...

  5. spring boot 使用拦截器,注解 实现 权限过滤

    http://www.cnblogs.com/zhangXingSheng/p/7744997.html spring boot 使用拦截器 实现 用户登录拦截 http://www.cnblogs. ...

  6. struts2学习笔记--拦截器(Interceptor)和登录权限验证Demo

    理解 Interceptor拦截器类似于我们学过的过滤器,是可以在action执行前后执行的代码.是我们做web开发是经常使用的技术,比如权限控制,日志.我们也可以把多个interceptor连在一起 ...

  7. [转载] Spring MVC - 处理器拦截器

    5.1.处理器拦截器简介 Spring Web MVC的处理器拦截器(如无特殊说明,下文所说的拦截器即处理器拦截器)类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理.   ...

  8. [Spring MVC] - Interceptor 拦截器

    Spring MVC中的Interceptor与Struts2的差不多. 下面是一个简单的Interceptor登陆验证例子: 1.需要在spring的配置文件中加入这段: <!-- 自定义拦截 ...

  9. spring mvc 配置文件拦截器过滤url

    最近在用spring mvc拦截器,sprin 版本号4.0.6.RELEASE, <mvc:interceptor> <mvc:mapping path="/admin/ ...

随机推荐

  1. 【C语言学习】-01 C基础

    本文目录: 0.进制转换 1.C数据类型 2.常量变量 3.运算符 4.表达式 5.格式化输入输出 回到顶部 0.进制转换 在计算机中存储的数据,主要是以二进制形式存在,而我们生活中主要使用的有十进制 ...

  2. CCNA 6.3

    no encapsulation ppp(默认是encapsulation hdlc 在encapsulation ppp 后想要改回 hdlc 除了可用encapsulation hdlc外,还可以 ...

  3. 看项目得到info_freeCsdn-01闪屏页面

    /** * 渐变展示启动屏 */ private void startAnimation() { Animation aa = new Animation() { }; aa.setDuration( ...

  4. fastboot 刷system.img 提示 sending 'system' (*KB)... FAILED (remote: data too large)

    华为G6-C00卡刷提示OEMSBL错误,只能线刷 ,但是官方找不到线刷img镜像,无奈 网上下了个可以线刷的工具套件 流氓ROM . 使用HuaweiUpdateExtractor(工具百度)把官方 ...

  5. sql server2014各版本对比(连接)

    简单的说,sql server 2014为企业版(全功能).BI版.标准版. SQL Server 2014 各个版本支持的功能 http://msdn.microsoft.com/zh-cn/lib ...

  6. SVG 2D入门4 - 笔画与填充

    前面我们重点都在总结各类形状,文本和图片,接下来,我们还是和讨论canvas一样,总结一下颜色处理,也就是填充和边框效果:你会发现这里的内容与canvas基本上是一致的.这些属性既可以以属性的形式写在 ...

  7. 在MyEclipse上搭建web服务器

    a)       Servlet是什么? Servlet(服务器端小程序)是使用Java语言编写的服务器端程序[o1] ,可以使用脚本语言,生成动态的web页. b)      Servlet的架构? ...

  8. IOS网络开发概述

    概览 大部分应用程序都或多或少会牵扯到网络开发,例如说新浪微博.微信等,这些应用本身可能采用iOS开发,但是所有的数据支撑都是基于后台网络服务器的.如今,网络编程越来越普遍,孤立的应用通常是没有生命力 ...

  9. UITableView错误 ‘unable to dequeue a cell with identifier Cell'

    - (id)dequeueReusableCellWithIdentifier:(NSString *)identifier; - (id)dequeueReusableCellWithIdentif ...

  10. Redis - list类型操作

    list类型操作 设置操作:lpush:    lpush key value            在list左侧插入value rpush:    rpush key value          ...