SpringMVC拦截器+Spring自定义注解实现权限验证
设计思路
主要针对需要登录后操作的接口进行校验。接入层在对外暴露接口后,网页、APP、第三方等等途径进行访问接口。用户请求首先会被SpringMVC拦截器拦截到,在拦截器里第一步就是需要校验用户的登录身份(由于是分布式系统这里采用的是userId+accessToken方式来校验),登录校验通过之后再进行用户权限校验,此时会自动拦截@AuthValidate注解的method(核心),如果权限校验失败则抛出权限不足异常,否则校验通过之后再执行具体接口并返回结果。
1、自定义注解
package com.mao.auth;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
*
* 项目名称:---
* 模块名称:接入层
* 功能描述:权限定义
* 创建人: mao2080@sina.com
* 创建时间:2017年5月9日 下午8:41:05
* 修改人: mao2080@sina.com
* 修改时间:2017年5月9日 下午8:41:05
*/
@Target(value = ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
@Documented
public @interface AuthValidate { /**
*
* 描述:权限定义
* @author mao2080@sina.com
* @created 2017年5月8日 上午11:36:41
* @since
* @return 权限代码
*/
AuthCode value() default AuthCode.Allow; }
2、权限枚举
package com.mao.auth; /**
*
* 项目名称:---
* 模块名称:接入层
* 功能描述:权限类型枚举
* 创建人: mao2080@sina.com
* 创建时间:2017年5月8日 上午11:43:12
* 修改人: mao2080@sina.com
* 修改时间:2017年5月8日 上午11:43:12
*/
public enum AuthCode { Allow("00000", "00000", "允许访问"), /******************客户权限******************/ AU0001("100001", "AU0001", "新增用户", "新增用户"), AU0002("100002", "AU0002", "删除用户", "批量删除用户"); /**权限标识 */
private String authId; /**权限编码 */
private String authCode; /**权限名称 */
private String authName; /**权限描述 */
private String authDesc; /**
*
* 描述:构建设备类型
* @author mao2080@sina.com
* @created 2017年3月22日 上午13:50:58
* @since
* @param authId 权限标识
* @param authCode 权限编码
* @param authName 权限名称
* @return
*/
private AuthCode(String authId, String authCode, String authName) {
this.authId = authId;
this.authCode = authCode;
this.authName = authName;
} /**
*
* 描述:构建设备类型
* @author mao2080@sina.com
* @created 2017年3月22日 上午13:50:58
* @since
* @param authId 权限标识
* @param authCode 权限编码
* @param authName 权限名称
* @param authDesc 权限描述
* @return
*/
private AuthCode(String authId, String authCode, String authName, String authDesc) {
this.authId = authId;
this.authCode = authCode;
this.authName = authName;
this.authDesc = authDesc;
} public String getAuthId() {
return authId;
} public void setAuthId(String authId) {
this.authId = authId;
} public String getAuthCode() {
return authCode;
} public void setAuthCode(String authCode) {
this.authCode = authCode;
} public String getAuthDesc() {
return authDesc;
} public void setAuthDesc(String authDesc) {
this.authDesc = authDesc;
} public String getAuthName() {
return authName;
} public void setAuthName(String authName) {
this.authName = authName;
} @Override
public String toString() {
return String.format("authId:%s, authCode:%s, authName:%s, authDesc:%s", this.authId, this.authCode, this.authName, this.authDesc);
} }
3、Controller使用自定义注解
package com.mao.controller; import javax.servlet.http.HttpServletRequest; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import com.mao.auth.AuthCode;
import com.mao.auth.AuthValidate;
import com.mao.beans.ResObject;
import com.mao.exception.BusinessException; /**
*
* 项目名称:---
* 模块名称:接入层
* 功能描述:用户控制层
* 创建人: mao2080@sina.com
* 创建时间:2017年5月9日 下午8:15:50
* 修改人: mao2080@sina.com
* 修改时间:2017年5月9日 下午8:15:50
*/
@Controller
@RequestMapping("/userController")
public class UserController { /**日志*/
@SuppressWarnings("unused")
private static final Log loger = LogFactory.getLog(UserController.class); /**
*
* 描述:新增用户
* @author mao2080@sina.com
* @created 2017年5月9日 下午8:16:41
* @since
* @param request
* @return
* @throws BusinessException
*/
@RequestMapping("/createUser")
@ResponseBody
@AuthValidate(AuthCode.AU0001)
public ResObject createUser(HttpServletRequest request) throws BusinessException{
//业务代码
return new ResObject();
} /**
*
* 描述:新增用户
* @author mao2080@sina.com
* @created 2017年5月9日 下午8:16:41
* @since
* @param request
* @return
* @throws BusinessException
*/
@RequestMapping("/deleteUser")
@ResponseBody
@AuthValidate(AuthCode.AU0002)
public ResObject deleteUser(HttpServletRequest request) throws BusinessException{
//业务代码
return new ResObject();
}
}
4、SpringMVC拦截器
package com.mao.interceptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView; import com.mao.auth.AuthCode;
import com.mao.auth.AuthValidate;
import com.mao.exception.BusinessException;
import com.mao.util.JsonUtil; /**
*
* 项目名称:---
* 模块名称:接入层
* 功能描述:用户登录拦截器(利用SpringMVC自定义拦截器实现)
* 创建人: mao2080@sina.com
* 创建时间:2017年4月25日 下午8:53:49
* 修改人: mao2080@sina.com
* 修改时间:2017年4月25日 下午8:53:49
*/
public class UserLoginInterceptor implements HandlerInterceptor { /**
*
* 描述:构造函数
* @author mao2080@sina.com
* @created 2017年4月28日 下午5:20:34
* @since
* @param accessService
*/
public UserLoginInterceptor() { } /**
*
* 描述:执行方法前
* @author mao2080@sina.com
* @created 2017年4月25日 下午9:01:44
* @since
* @param request HttpServletRequest
* @param response HttpServletResponse
* @param handler handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
try {
//校验登录
this.userLoginValidate(request);
//校验权限
this.userAuthValidate(request, handler);
} catch (Exception e) {
e.printStackTrace();
printMessage(response, e);
return false;
}
return true;
} /**
*
* 描述:输出到前端
* @author mao2080@sina.com
* @created 2017年4月28日 上午11:00:25
* @since
* @param response 响应
* @param res 对象
* @throws Exception
*/
public static void printMessage(HttpServletResponse response, Object res) throws Exception{
PrintWriter writer = null;
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=utf-8");
try {
writer = response.getWriter();
writer.print(JsonUtil.toJson(res));
} catch (Exception e) {
e.printStackTrace();
} finally {
if (writer != null){
writer.close();
}
}
} @Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } /**
*
* 描述:用户登录校验
* @author mao2080@sina.com
* @created 2017年5月9日 下午8:27:25
* @since
* @param request
* @throws BusinessException
*/
private void userLoginValidate(HttpServletRequest request) throws BusinessException {
//校验代码
} /**
*
* 描述:用户权限校验
* @author mao2080@sina.com
* @created 2017年5月4日 下午8:34:09
* @since
* @param request HttpServletRequest
* @param handler
* @return
* @throws BusinessException
*/
private void userAuthValidate(HttpServletRequest request, Object handler) throws BusinessException {
AuthValidate validate = ((HandlerMethod) handler).getMethodAnnotation(AuthValidate.class);
if(validate == null){
throw new BusinessException("未配置自定义注解");
}
String funcCode = validate.value().getAuthCode();
if(funcCode.equals(AuthCode.Allow.getAuthCode())){
return;
}
String authId = validate.value().getAuthId();
List<String> auths = new ArrayList<>();//模拟从缓存或者从数据库中查询出对应用户的权限
if(!auths.contains(authId)){
throw new BusinessException("权限不足");
}
} }
5、拦截器配置
package com.mao.interceptor; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; /**
*
* 项目名称:---
* 模块名称:接入层
* 功能描述:拦截器配置
* 创建人: mao2080@sina.com
* 创建时间:2017年5月9日 下午8:54:00
* 修改人: mao2080@sina.com
* 修改时间:2017年5月9日 下午8:54:00
*/
@Configuration
@ComponentScan(basePackages={"com.mao"})
@EnableWebMvc
public class WebConfiguration extends WebMvcConfigurerAdapter { /**日志*/
private static final Log loger = LogFactory.getLog(WebConfiguration.class); /**
*
* 描述:构造函数
* @author mao2080@sina.com
* @created 2017年5月3日 下午4:48:41
* @since
*/
public WebConfiguration() {
loger.info("开启系统登录拦截");
} /**
*
* 描述:添加拦截器
* @author mao2080@sina.com
* @created 2017年4月25日 下午8:50:54
* @since
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
this.excludeUserLogin(registry.addInterceptor(new UserLoginInterceptor()));
} /**
*
* 描述:拦截请求
* @author mao2080@sina.com
* @created 2017年5月9日 下午8:55:28
* @since
* @param registration
*/
public void excludeUserLogin(InterceptorRegistration registration){
registration.addPathPatterns("/userController/*");
} }
6、返回对象
package com.mao.beans; import java.io.Serializable; /**
*
* 项目名称:
* 模块名称:
* 功能描述:
* 创建人: mao2080@sina.com
* 创建时间:2017年5月3日 下午6:37:11
* 修改人: mao2080@sina.com
* 修改时间:2017年5月3日 下午6:37:11
*/
public class ResObject implements Serializable{ /**序列号*/
private static final long serialVersionUID = 589903502110209046L; /**返回代码*/
private int code = 200; /**返回信息*/
private String desc = "Success."; /**返回数据*/
private Object data; /**
*
* 构建函数
* @author mao2080@sina.com
* @created 2017年3月24日 下午4:25:23
* @since
*/
public ResObject() { } /**
*
* 描述:构造函数
* @author mao2080@sina.com
* @created 2017年4月18日 下午3:32:26
* @since
* @param data 数据
*/
public ResObject(Object data) {
super();
this.data = data;
} /**
*
* 构建函数
* @author mao2080@sina.com
* @created 2017年3月24日 下午4:25:35
* @since
* @param code 返回代码
* @param desc 返回信息
*/
public ResObject(int code, String desc) {
super();
this.code = code;
this.desc = desc;
} /**
*
* 构建函数
* @author mao2080@sina.com
* @created 2017年3月24日 下午4:25:39
* @since
* @param code 返回代码
* @param desc 返回信息
* @param data 返回数据
*/
public ResObject(int code, String desc, Object data) {
super();
this.code = code;
this.desc = desc;
this.data = data;
} public Object getData() {
return data;
} public void setData(Object data) {
this.data = data;
} public int getCode() {
return code;
} public void setCode(int code) {
this.code = code;
} public String getDesc() {
return desc;
} public void setDesc(String desc) {
this.desc = desc;
} }
ResObject
7、异常类
package com.mao.exception; /**
*
* 项目名称:---
* 模块名称:接入层
* 功能描述:异常类
* 创建人: mao2080@sina.com
* 创建时间:2017年5月9日 下午8:22:21
* 修改人: mao2080@sina.com
* 修改时间:2017年5月9日 下午8:22:21
*/
public class BusinessException extends Exception{ public BusinessException() { } public BusinessException(String message) {
super(message);
} }
BusinessException
8、json工具类
package com.mao.util; import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.mao.exception.BusinessException; /**
*
* 项目名称:---
* 模块名称:常用工具类
* 功能描述:json工具类
* 创建人: mao2080@sina.com
* 创建时间:2017年3月28日 上午11:56:15
* 修改人: mao2080@sina.com
* 修改时间:2017年3月28日 上午11:56:15
*/
public class JsonUtil { /**
*
* 描述:将对象格式化成json字符串
* @author mao2080@sina.com
* @created 2017年4月1日 下午4:38:18
* @since
* @param object 对象
* @return json字符串
* @throws BusinessException
*/
public static String toJson(Object object) throws BusinessException {
try {
return JSON.toJSONString(object, new SerializerFeature[] {
SerializerFeature.WriteMapNullValue,
SerializerFeature.DisableCircularReferenceDetect,
SerializerFeature.WriteNonStringKeyAsString });
} catch (Exception e) {
throw new BusinessException();
}
} /**
*
* 描述:将对象格式化成json字符串(PrettyFormat格式)
* @author mao2080@sina.com
* @created 2017年4月1日 下午4:38:18
* @since
* @param object 对象
* @return json字符串
* @throws BusinessException
*/
public static String toJsonFormat(Object object) throws BusinessException {
try {
return JSON.toJSONString(object, new SerializerFeature[] {
SerializerFeature.WriteMapNullValue,
SerializerFeature.PrettyFormat,
SerializerFeature.DisableCircularReferenceDetect,
SerializerFeature.WriteNonStringKeyAsString });
} catch (Exception e) {
throw new BusinessException();
}
} /**
*
* 描述:转Map
* @author mao2080@sina.com
* @created 2017年4月1日 下午5:00:20
* @since
* @param obj 对象
* @return object
* @throws BusinessException
*/
public static Object toJsonObject(Object obj) throws BusinessException {
try {
return JSON.toJSON(obj);
} catch (Exception e) {
throw new BusinessException();
}
} /**
*
* 描述:将json串转为对象
* @author mao2080@sina.com
* @created 2017年4月1日 下午5:01:23
* @since
* @param jsonString json串
* @param clazz 对象
* @return
* @throws BusinessException
*/
public static <T> T fromJson(String jsonString, Class<T> clazz) throws BusinessException {
try {
if (StringUtils.isBlank(jsonString)) {
return null;
}
return (T) JSON.parseObject(jsonString, clazz);
} catch (Exception e) {
throw new BusinessException();
}
} /**
*
* 描述:暂时不开通
* @author mao2080@sina.com
* @created 2017年4月1日 下午5:08:12
* @since
* @param jsonString
* @return
* @throws Exception
*/
@SuppressWarnings("unused")
private static <T> T fromJson(String jsonString) throws Exception {
return JSON.parseObject(jsonString, new TypeReference<T>() {
}, new Feature[0]);
} }
JsonUtil
SpringMVC拦截器+Spring自定义注解实现权限验证的更多相关文章
- struts2拦截器加自定义注解实现权限控制
https://blog.csdn.net/paul342/article/details/51436565 今天结合Java的Annotation和Struts2进行注解拦截器权限控制. 功能需求: ...
- SpringMVC拦截器2(资源和权限管理)(作为补充说明)
SpringMVC拦截器(资源和权限管理) 1.DispatcherServlet SpringMVC具有统一的入口DispatcherServlet,所有的请求都通过DispatcherServle ...
- SpringMVC(9)实现注解式权限验证
对大部分系统来说都需要权限管理来决定不同用户可以看到哪些内容,那么如何在Spring MVC中实现权限验证呢?当然我们可以继续使用servlet中的过滤器Filter来实现.但借助于Spring MV ...
- Spring MVC基础知识整理➣拦截器和自定义注解
概述 Spring MVC中通过注解来对方法或者类进行动态的说明或者标注,类似于配置标识文件的属性信息.当标注的类或者方式被使用时候,通过提取注解信息来达到对类的动态处理.在 MVC中,我们常用的注解 ...
- [Java]利用拦截器和自定义注解做登录以及权限验证
1.自定义注解 需要验证登录的注解 package com.etaofinance.wap.common; import java.lang.annotation.Documented; import ...
- 拦截器和自定义注解@interface
1 .拦截器(Interceptor): 用于在某个方法被访问之前进行拦截,然后在Handler执行之前或之后加入某些操作,其实就是AOP的一种实现策略. 拦截用户的请求并进行相应的处理,比如:判断用 ...
- SpringBoot 拦截器和自定义注解判断请求是否合法
应用场景举例: 当不同身份的用户请求一个接口时,用来校验用户某些身份,这样可以对单个字段数据进行精确权限控制,具体看代码注释 自定义注解 /** * 对比请求的用户身份是否符合 * @author l ...
- SpringMVC拦截器和@ResponseBody注解冲突
在使用@ResponseBody注解后controller方法只会返回ModelandView对象的数据模型,不会返回视图,这样有很多好处,但是如果在拦截器中进行了页面转发,在满足页面转发条件时,不会 ...
- SpringMVC(10)实现注解式权限验证
在项目中如何处理出现的异常,在每个可能出现异常的地方都写代码捕捉异常?这显然是不合理的,当项目越来越大是也是不可维护的.那么如何保证我们处理异常的代码精简且便于维护呢?这就是本篇要讲的内容->异 ...
随机推荐
- 网络架构,七层协议,三次握手四次挥手,socket套接字简单编程
一.单机架构 应用领域: 植物大战僵尸 office 二.CS架构 应用领域: QQ 大型网络游戏 计算机发展初期用户去取数据,直接就去主机拿,从这里开始就分出了客户端和服务端. 客户端:用户安装的软 ...
- 用Kindle阅读PDF最简单的3个方法!
老实说,Kindle 对于PDF文件是很不友好的,经常会出现各种排版问题,所以,对电子阅读器方面比较了解的同学都知道,如果需要经常用阅读器查看PDF文件的话,最好还是买一款更大屏幕的设备,而Kindl ...
- SQL语句中*号的缺点
我觉得这篇博客说的比较好,参考借鉴一下:https://blog.csdn.net/weixin_44588186/article/details/87263756
- vue history模式 ios微信分享坑
vue history模式 ios微信分享坑 问题分析:因为苹果分享会是调取签名失败是因为:苹果在微信中浏览器机制和安卓不同,有IOS缓存问题,和IOS对单页面的优化问题,通俗点说安卓进行页面跳转分享 ...
- Apple历史应用以及开发工具版本(Xcode官方历史版本等等)
1.Xcode 官方历史版本下载:(需要登录开发者账号) https://developer.apple.com/download/more/
- ubuntu apache 一个ip绑定多个域名,发布目录
1.将www.aaa.com 与 www.bbb.com 的DNS解析到你的服务器上 2.添加两个发布目录 /var/www/html/aaa /var/www/html/bbb 3.修改配置文件. ...
- 英特尔的Gen11集成显卡性能再次发力
这是英特尔首个达到 1 TeraFLOP 算力的图形模块,与第九代酷睿移动版的性能相比,15W Ice Lake-U 在游戏测试场景中,平均帧速率的性能提升了 40%. 与同等的 AMD 产品相比,英 ...
- 接口测试参数化详解(Jmeter)
简介 接口测试是目前最主流的自动化测试手段,它组合不同的参数向服务器发送请求,接受和解析响应结果,通过测试数据的交换逻辑来验证服务端程序工作的正确性.我们在测试过程中需要考虑不同的输入组合,来覆盖不同 ...
- [工具] BurpSuite--XssValidator插件
0x00 安装 所需软件: 1.burpsuite 2.xssvalidator 源码:https://github.com/nVisium/xssValidator(按照编译指导编译) burpsu ...
- nginx的反向代理和配置
最近有打算研读nginx源代码,看到网上介绍nginx可以作为一个反向代理服务器完成负载均衡.所以搜罗了一些关于反向代理服务器的内容,整理综合. 一 概述 反向代理(Reverse Proxy)方式 ...